Compare commits
	
		
			62 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8d3a7a6048 | ||
| 
						 | 
					c047df31bb | ||
| 
						 | 
					1f2d9a7175 | ||
| 
						 | 
					05b9507a7c | ||
| 
						 | 
					51b3dfafa6 | ||
| 
						 | 
					eaeb88b504 | ||
| 
						 | 
					eb9fcfd261 | ||
| 
						 | 
					73c65171c6 | ||
| 
						 | 
					88de129781 | ||
| 
						 | 
					e96d1e6c29 | ||
| 
						 | 
					c016258c24 | ||
| 
						 | 
					4ccfd647c9 | ||
| 
						 | 
					46db487a09 | ||
| 
						 | 
					8c9ccc3cbd | ||
| 
						 | 
					bd479ed778 | ||
| 
						 | 
					44f1713c60 | ||
| 
						 | 
					56f9d4dd84 | ||
| 
						 | 
					99b4fe71a4 | ||
| 
						 | 
					a3bd6ac710 | ||
| 
						 | 
					656a5b36dd | ||
| 
						 | 
					0333e60bba | ||
| 
						 | 
					3cd7c36202 | ||
| 
						 | 
					9e589a0c0e | ||
| 
						 | 
					76e9b1e825 | ||
| 
						 | 
					86abda661b | ||
| 
						 | 
					dddc3e3d51 | ||
| 
						 | 
					8a13fe18b4 | ||
| 
						 | 
					258b187f5d | ||
| 
						 | 
					a5d89fc2db | ||
| 
						 | 
					97c0560717 | ||
| 
						 | 
					9ad094cbf7 | ||
| 
						 | 
					22530bea38 | ||
| 
						 | 
					c729463bde | ||
| 
						 | 
					4e703c457c | ||
| 
						 | 
					83dc663d2d | ||
| 
						 | 
					6090505f47 | ||
| 
						 | 
					c89b1296a2 | ||
| 
						 | 
					a6a362ab1b | ||
| 
						 | 
					0bd4932f0c | ||
| 
						 | 
					541faa7847 | ||
| 
						 | 
					1a71970f82 | ||
| 
						 | 
					6e2b7102c9 | ||
| 
						 | 
					0969d8c13e | ||
| 
						 | 
					d8825b020d | ||
| 
						 | 
					5ed68de345 | ||
| 
						 | 
					6125c577aa | ||
| 
						 | 
					a9fc9a0dce | ||
| 
						 | 
					393cb9d820 | ||
| 
						 | 
					0174eb3523 | ||
| 
						 | 
					6286318db9 | ||
| 
						 | 
					bf16469738 | ||
| 
						 | 
					89b22d61b6 | ||
| 
						 | 
					29234d826d | ||
| 
						 | 
					993fe31fac | ||
| 
						 | 
					44fc6e6554 | ||
| 
						 | 
					cc77d8eb82 | ||
| 
						 | 
					1ca4036fca | ||
| 
						 | 
					1ee5bde1b3 | ||
| 
						 | 
					43e29a9904 | ||
| 
						 | 
					6e3d429942 | ||
| 
						 | 
					534a948916 | ||
| 
						 | 
					304b9eb439 | 
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							@@ -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 \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								binder.conf
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								binder.conf
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ all: debug release pkgconfig
 | 
			
		||||
 | 
			
		||||
VERSION_MAJOR = 1
 | 
			
		||||
VERSION_MINOR = 1
 | 
			
		||||
VERSION_RELEASE = 8
 | 
			
		||||
VERSION_RELEASE = 17
 | 
			
		||||
 | 
			
		||||
# Version for pkg-config
 | 
			
		||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
Name: ofono-binder-plugin
 | 
			
		||||
 | 
			
		||||
Version: 1.1.8
 | 
			
		||||
Version: 1.1.17
 | 
			
		||||
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.11
 | 
			
		||||
%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.28+git8
 | 
			
		||||
 | 
			
		||||
BuildRequires: pkgconfig
 | 
			
		||||
BuildRequires: ofono-devel >= %{ofono_version}
 | 
			
		||||
@@ -55,7 +55,6 @@ make %{_smp_mflags} -C lib LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
 | 
			
		||||
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 +102,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
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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_GET_CALL_FORWARD_STATUS) {
 | 
			
		||||
        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,6 +343,9 @@ 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);
 | 
			
		||||
 | 
			
		||||
@@ -311,7 +355,7 @@ binder_call_forwarding_query(
 | 
			
		||||
        DBG_(self, "cls %d => %d", cls, RADIO_SERVICE_CLASS_NONE);
 | 
			
		||||
        cls = RADIO_SERVICE_CLASS_NONE;
 | 
			
		||||
    }
 | 
			
		||||
    binder_call_forwarding_call(self, RADIO_REQ_GET_CALL_FORWARD_STATUS,
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
@@ -340,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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										131
									
								
								src/binder_cbs.c
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								src/binder_cbs.c
									
									
									
									
									
								
							@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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, <e->mcc);
 | 
			
		||||
        binder_read_string16_parse_int(reader, <e->mnc);
 | 
			
		||||
        gbinder_reader_read_int32(reader, <e->ci);
 | 
			
		||||
        gbinder_reader_read_int32(reader, <e->pci);
 | 
			
		||||
        gbinder_reader_read_int32(reader, <e->tac);
 | 
			
		||||
        gbinder_reader_read_int32(reader, <e->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, <e->signalStrength);
 | 
			
		||||
        gbinder_reader_read_int32(reader, <e->rsrp);
 | 
			
		||||
        gbinder_reader_read_int32(reader, <e->rsrq);
 | 
			
		||||
        gbinder_reader_read_int32(reader, <e->rssnr);
 | 
			
		||||
        gbinder_reader_read_int32(reader, <e->cqi);
 | 
			
		||||
        gbinder_reader_read_int32(reader, <e->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, ®istered);
 | 
			
		||||
        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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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
											
										
									
								
							@@ -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 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,8 @@
 | 
			
		||||
#include <radio_request.h>
 | 
			
		||||
#include <radio_request_group.h>
 | 
			
		||||
 | 
			
		||||
#include <radio_network_types.h>
 | 
			
		||||
 | 
			
		||||
#include <gbinder_reader.h>
 | 
			
		||||
#include <gutil_macros.h>
 | 
			
		||||
#include <gutil_misc.h>
 | 
			
		||||
@@ -82,10 +84,14 @@ binder_ims_reg_query_done(
 | 
			
		||||
    BinderBase* base = &self->base;
 | 
			
		||||
    BinderImsReg* ims = &self->pub;
 | 
			
		||||
    gboolean registered = FALSE;
 | 
			
		||||
    guint32 code =
 | 
			
		||||
        radio_client_aidl_interface(self->g->client) == RADIO_NETWORK_INTERFACE ?
 | 
			
		||||
            RADIO_NETWORK_RESP_GET_IMS_REGISTRATION_STATE :
 | 
			
		||||
            RADIO_RESP_GET_IMS_REGISTRATION_STATE;
 | 
			
		||||
 | 
			
		||||
    if (status != RADIO_TX_STATUS_OK) {
 | 
			
		||||
        ofono_error("getImsRegistrationState failed");
 | 
			
		||||
    } else if (resp != RADIO_RESP_GET_IMS_REGISTRATION_STATE) {
 | 
			
		||||
    } else if (resp != code) {
 | 
			
		||||
        ofono_error("Unexpected getImsRegistrationState response %d", resp);
 | 
			
		||||
    } else if (error != RADIO_ERROR_NONE) {
 | 
			
		||||
        DBG_(self, "%s", binder_radio_error_string(error));
 | 
			
		||||
@@ -120,8 +126,12 @@ void
 | 
			
		||||
binder_ims_reg_query(
 | 
			
		||||
    BinderImsRegObject* self)
 | 
			
		||||
{
 | 
			
		||||
    guint32 code =
 | 
			
		||||
        radio_client_aidl_interface(self->g->client) == RADIO_NETWORK_INTERFACE ?
 | 
			
		||||
            RADIO_NETWORK_REQ_GET_IMS_REGISTRATION_STATE :
 | 
			
		||||
            RADIO_REQ_GET_IMS_REGISTRATION_STATE;
 | 
			
		||||
    RadioRequest* req = radio_request_new2(self->g,
 | 
			
		||||
        RADIO_REQ_GET_IMS_REGISTRATION_STATE, NULL,
 | 
			
		||||
        code, NULL,
 | 
			
		||||
        binder_ims_reg_query_done, NULL, self);
 | 
			
		||||
 | 
			
		||||
    radio_request_submit(req);
 | 
			
		||||
@@ -200,13 +210,16 @@ binder_ims_reg_new(
 | 
			
		||||
                binder_ext_ims_add_state_handler(self->ext,
 | 
			
		||||
                    binder_ims_ext_state_changed, self);
 | 
			
		||||
        } else {
 | 
			
		||||
            guint32 code =
 | 
			
		||||
                radio_client_aidl_interface(client) == RADIO_NETWORK_INTERFACE ?
 | 
			
		||||
                    RADIO_NETWORK_IND_IMS_NETWORK_STATE_CHANGED :
 | 
			
		||||
                    RADIO_IND_IMS_NETWORK_STATE_CHANGED;
 | 
			
		||||
            DBG_(self, "using ims radio api");
 | 
			
		||||
            self->g = radio_request_group_new(client); /* Keeps ref to client */
 | 
			
		||||
 | 
			
		||||
            /* Register event handler */
 | 
			
		||||
            self->event_id[EVENT_IMS_NETWORK_STATE_CHANGED] =
 | 
			
		||||
                radio_client_add_indication_handler(client,
 | 
			
		||||
                    RADIO_IND_IMS_NETWORK_STATE_CHANGED,
 | 
			
		||||
                    code,
 | 
			
		||||
                    binder_ims_reg_state_changed, self);
 | 
			
		||||
 | 
			
		||||
            /* Query the initial state */
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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, ext, 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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1467
									
								
								src/binder_netreg.c
									
									
									
									
									
								
							
							
						
						
									
										1467
									
								
								src/binder_netreg.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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
									
								
							
							
						
						
									
										66
									
								
								src/binder_oplist.c
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										60
									
								
								src/binder_oplist.h
									
									
									
									
									
										Normal 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:
 | 
			
		||||
 */
 | 
			
		||||
@@ -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,16 @@ 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);
 | 
			
		||||
    for (RADIO_AIDL_INTERFACE 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 +486,16 @@ 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);
 | 
			
		||||
    for (RADIO_AIDL_INTERFACE 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 +525,17 @@ binder_plugin_check_if_started(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
binder_plugin_is_slot_client_connected(
 | 
			
		||||
    BinderSlot* slot)
 | 
			
		||||
{
 | 
			
		||||
    for (RADIO_AIDL_INTERFACE i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
 | 
			
		||||
        if (slot->client[i]) return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
binder_plugin_slot_shutdown(
 | 
			
		||||
@@ -567,24 +599,29 @@ 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_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 (RADIO_AIDL_INTERFACE 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 +709,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;
 | 
			
		||||
@@ -704,11 +784,18 @@ binder_plugin_slot_enabled_changed(
 | 
			
		||||
{
 | 
			
		||||
    BinderSlot* slot = user_data;
 | 
			
		||||
 | 
			
		||||
    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 (RADIO_AIDL_INTERFACE 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 +806,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 +827,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 +899,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 +946,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 +970,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 +1044,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 +1066,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 +1079,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 +1103,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 +1129,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 +1151,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 +1178,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 +1209,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 +1297,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 +1334,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 +1352,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 +1404,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 +1493,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 +1585,7 @@ binder_plugin_create_slot(
 | 
			
		||||
    GError* error = NULL;
 | 
			
		||||
    const char* group = name;
 | 
			
		||||
    GUtilInts* ints;
 | 
			
		||||
    char **strv;
 | 
			
		||||
    char* sval;
 | 
			
		||||
    int ival;
 | 
			
		||||
 | 
			
		||||
@@ -1604,6 +1787,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 +2101,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 +2138,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 +2362,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 +2403,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 +2423,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 +2446,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 +2486,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 +2549,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 +2568,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 +2596,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 +2615,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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										405
									
								
								src/binder_sim.c
									
									
									
									
									
								
							
							
						
						
									
										405
									
								
								src/binder_sim.c
									
									
									
									
									
								
							@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										384
									
								
								src/binder_sms.c
									
									
									
									
									
								
							
							
						
						
									
										384
									
								
								src/binder_sms.c
									
									
									
									
									
								
							@@ -31,6 +31,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 +82,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 +228,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 +260,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 +297,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 +354,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");
 | 
			
		||||
@@ -373,12 +399,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 +417,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 +624,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 +741,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 +769,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 +824,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 +850,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 +891,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 +912,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 +1022,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 +1070,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 +1085,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);
 | 
			
		||||
@@ -911,9 +1116,11 @@ binder_sms_on_sim(
 | 
			
		||||
    gint32 rec;
 | 
			
		||||
 | 
			
		||||
    ofono_info("new sms on sim");
 | 
			
		||||
    guint32 ind_code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
 | 
			
		||||
        RADIO_MESSAGING_IND_NEW_SMS_ON_SIM : RADIO_IND_NEW_SMS_ON_SIM;
 | 
			
		||||
 | 
			
		||||
    /* newSmsOnSim(RadioIndicationType type, int32 recordNumber); */
 | 
			
		||||
    GASSERT(code == RADIO_IND_NEW_SMS_ON_SIM);
 | 
			
		||||
    GASSERT(code == ind_code);
 | 
			
		||||
    gbinder_reader_copy(&reader, args);
 | 
			
		||||
    if (gbinder_reader_read_int32(&reader, &rec)) {
 | 
			
		||||
        DBG("rec %d", rec);
 | 
			
		||||
@@ -940,15 +1147,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 +1199,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) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										131
									
								
								src/binder_stk.c
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								src/binder_stk.c
									
									
									
									
									
								
							@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,10 +256,16 @@ 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);
 | 
			
		||||
@@ -274,6 +295,8 @@ binder_ussd_notify(
 | 
			
		||||
        } else {
 | 
			
		||||
            ofono_ussd_notify(self->ussd, type, 0, NULL, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        g_free(msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -291,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;
 | 
			
		||||
}
 | 
			
		||||
@@ -308,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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
#include <ofono/voicecall.h>
 | 
			
		||||
 | 
			
		||||
#include <radio_client.h>
 | 
			
		||||
#include <radio_instance.h>
 | 
			
		||||
#include <radio_request.h>
 | 
			
		||||
#include <radio_request_group.h>
 | 
			
		||||
#include <radio_util.h>
 | 
			
		||||
@@ -64,7 +65,10 @@ typedef struct binder_voicecall {
 | 
			
		||||
    GSList* calls;
 | 
			
		||||
    BinderExtCall* ext;
 | 
			
		||||
    BinderImsReg* ims_reg;
 | 
			
		||||
    RadioInstance* instance;
 | 
			
		||||
    RadioRequestGroup* g;
 | 
			
		||||
    RadioClient* network_client;
 | 
			
		||||
    RADIO_AIDL_INTERFACE interface_aidl;
 | 
			
		||||
    ofono_voicecall_cb_t cb;
 | 
			
		||||
    void* data;
 | 
			
		||||
    GUtilIntArray* local_release_ids;
 | 
			
		||||
@@ -262,6 +266,70 @@ binder_voicecall_info_new(
 | 
			
		||||
    return call;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
BinderVoiceCallInfo*
 | 
			
		||||
binder_voicecall_info_new_aidl(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
{
 | 
			
		||||
    BinderVoiceCallInfo* call = g_slice_new0(BinderVoiceCallInfo);
 | 
			
		||||
    struct ofono_call* oc = &call->oc;
 | 
			
		||||
    gboolean is_mt;
 | 
			
		||||
    gboolean is_voice;
 | 
			
		||||
    char* name;
 | 
			
		||||
    char* number;
 | 
			
		||||
 | 
			
		||||
    gsize address_parcel_size = binder_read_parcelable_size(reader);
 | 
			
		||||
 | 
			
		||||
    ofono_call_init(oc);
 | 
			
		||||
    if (address_parcel_size) {
 | 
			
		||||
        gsize address_data_read;
 | 
			
		||||
        gsize address_initial_size = gbinder_reader_bytes_read(reader);
 | 
			
		||||
 | 
			
		||||
        gbinder_reader_read_uint32(reader, &oc->status);
 | 
			
		||||
        gbinder_reader_read_uint32(reader, &oc->id);
 | 
			
		||||
        gbinder_reader_read_int32(reader, &oc->phone_number.type);
 | 
			
		||||
        gbinder_reader_read_bool(reader, NULL); /* isMpty */
 | 
			
		||||
        gbinder_reader_read_bool(reader, &is_mt);
 | 
			
		||||
        oc->direction = is_mt ?
 | 
			
		||||
            OFONO_CALL_DIRECTION_MOBILE_TERMINATED :
 | 
			
		||||
            OFONO_CALL_DIRECTION_MOBILE_ORIGINATED;
 | 
			
		||||
        gbinder_reader_read_int32(reader, NULL); /* als */
 | 
			
		||||
        gbinder_reader_read_bool(reader, &is_voice);
 | 
			
		||||
        oc->type = is_voice ?
 | 
			
		||||
            OFONO_CALL_MODE_VOICE :
 | 
			
		||||
            OFONO_CALL_MODE_UNKNOWN;
 | 
			
		||||
        gbinder_reader_read_bool(reader, NULL);
 | 
			
		||||
        number = gbinder_reader_read_string16(reader);
 | 
			
		||||
        if (number && strlen(number)) {
 | 
			
		||||
            oc->clip_validity = OFONO_CLIP_VALIDITY_VALID;
 | 
			
		||||
            g_strlcpy(oc->phone_number.number, number,
 | 
			
		||||
                OFONO_MAX_PHONE_NUMBER_LENGTH);
 | 
			
		||||
        } else {
 | 
			
		||||
            oc->clip_validity = OFONO_CLIP_VALIDITY_NOT_AVAILABLE;
 | 
			
		||||
        }
 | 
			
		||||
        gbinder_reader_read_int32(reader, NULL); /* als */
 | 
			
		||||
        name = gbinder_reader_read_string16(reader);
 | 
			
		||||
        if (name && strlen(name)) {
 | 
			
		||||
            g_strlcpy(oc->name, name, OFONO_MAX_CALLER_NAME_LENGTH);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Ignore rest of values for now
 | 
			
		||||
        address_data_read = gbinder_reader_bytes_read(reader) - address_initial_size;
 | 
			
		||||
        while (address_data_read < address_parcel_size) {
 | 
			
		||||
            gbinder_reader_read_uint32(reader, NULL);
 | 
			
		||||
            address_data_read += sizeof(guint32);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        DBG("[id=%d,status=%d,type=%d,number=%s,name=%s]", oc->id,
 | 
			
		||||
            oc->status, oc->type, oc->phone_number.number, oc->name);
 | 
			
		||||
 | 
			
		||||
        g_free(name);
 | 
			
		||||
        g_free(number);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return call;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
BinderVoiceCallInfo*
 | 
			
		||||
binder_voicecall_info_ext_new(
 | 
			
		||||
@@ -437,7 +505,12 @@ binder_voicecall_map_cause(
 | 
			
		||||
 | 
			
		||||
        case RADIO_LAST_CALL_FAIL_NORMAL_UNSPECIFIED:
 | 
			
		||||
            call_status = binder_voicecall_status_with_id(self, cid);
 | 
			
		||||
            if (call_status == OFONO_CALL_STATUS_ACTIVE ||
 | 
			
		||||
            /* If call cid doesn't exist anymore, above method returns -1.
 | 
			
		||||
               This case can happen, when the cause response is received
 | 
			
		||||
               after the status response that removed the call from the
 | 
			
		||||
               list. We then assume that the remote is the cause. */
 | 
			
		||||
            if (call_status == -1 ||
 | 
			
		||||
                call_status == OFONO_CALL_STATUS_ACTIVE ||
 | 
			
		||||
                call_status == OFONO_CALL_STATUS_HELD ||
 | 
			
		||||
                call_status == OFONO_CALL_STATUS_DIALING ||
 | 
			
		||||
                call_status == OFONO_CALL_STATUS_ALERTING) {
 | 
			
		||||
@@ -479,23 +552,34 @@ binder_voicecall_lastcause_cb(
 | 
			
		||||
 | 
			
		||||
    if (status == RADIO_TX_STATUS_OK) {
 | 
			
		||||
        if (error == RADIO_ERROR_NONE) {
 | 
			
		||||
            if (resp == RADIO_RESP_GET_LAST_CALL_FAIL_CAUSE) {
 | 
			
		||||
            guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
                RADIO_VOICE_RESP_GET_LAST_CALL_FAIL_CAUSE :
 | 
			
		||||
                RADIO_RESP_GET_LAST_CALL_FAIL_CAUSE;
 | 
			
		||||
 | 
			
		||||
            if (resp == code) {
 | 
			
		||||
                GBinderReader reader;
 | 
			
		||||
                const RadioLastCallFailCauseInfo* info;
 | 
			
		||||
                gint32 cause_code;
 | 
			
		||||
 | 
			
		||||
                /*
 | 
			
		||||
                 * getLastCallFailCauseResponse(RadioResponseInfo,
 | 
			
		||||
                 *   LastCallFailCauseInfo failCauseinfo);
 | 
			
		||||
                 */
 | 
			
		||||
                gbinder_reader_copy(&reader, args);
 | 
			
		||||
                info = gbinder_reader_read_hidl_struct(&reader,
 | 
			
		||||
                    RadioLastCallFailCauseInfo);
 | 
			
		||||
                if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
 | 
			
		||||
                    info = gbinder_reader_read_hidl_struct(&reader,
 | 
			
		||||
                        RadioLastCallFailCauseInfo);
 | 
			
		||||
                    cause_code = info->causeCode;
 | 
			
		||||
                } else {
 | 
			
		||||
                    gbinder_reader_read_int32(&reader, &cause_code);
 | 
			
		||||
                    gbinder_reader_skip_string16(&reader);
 | 
			
		||||
                }
 | 
			
		||||
                if (info) {
 | 
			
		||||
                    enum ofono_disconnect_reason reason =
 | 
			
		||||
                        binder_voicecall_map_cause(self, cid, info->causeCode);
 | 
			
		||||
                        binder_voicecall_map_cause(self, cid, cause_code);
 | 
			
		||||
 | 
			
		||||
                    ofono_info("Call %d ended with cause %d -> ofono reason %d",
 | 
			
		||||
                        cid, info->causeCode, reason);
 | 
			
		||||
                        cid, cause_code, reason);
 | 
			
		||||
                    ofono_voicecall_disconnected(vc, cid, reason, NULL);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
@@ -540,8 +624,11 @@ binder_voicecall_set_calls(
 | 
			
		||||
                BinderVoiceCallLastCauseData* reqdata =
 | 
			
		||||
                    g_new0(BinderVoiceCallLastCauseData, 1);
 | 
			
		||||
                /* getLastCallFailCause(int32 serial); */
 | 
			
		||||
                guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
                    RADIO_VOICE_REQ_GET_LAST_CALL_FAIL_CAUSE :
 | 
			
		||||
                    RADIO_REQ_GET_LAST_CALL_FAIL_CAUSE;
 | 
			
		||||
                RadioRequest* req2 = radio_request_new2(self->g,
 | 
			
		||||
                    RADIO_REQ_GET_LAST_CALL_FAIL_CAUSE, NULL,
 | 
			
		||||
                    code, NULL,
 | 
			
		||||
                    binder_voicecall_lastcause_cb, g_free, reqdata);
 | 
			
		||||
 | 
			
		||||
                reqdata->self = self;
 | 
			
		||||
@@ -604,38 +691,54 @@ binder_voicecall_clcc_poll_cb(
 | 
			
		||||
    if (status == RADIO_TX_STATUS_OK) {
 | 
			
		||||
        if (error == RADIO_ERROR_NONE) {
 | 
			
		||||
            GBinderReader reader;
 | 
			
		||||
            gsize i, count = 0;
 | 
			
		||||
            gsize i;
 | 
			
		||||
 | 
			
		||||
            /* getCurrentCallsResponse(RadioResponseInfo, vec<Call> calls); */
 | 
			
		||||
            gbinder_reader_copy(&reader, args);
 | 
			
		||||
            if (resp == RADIO_RESP_GET_CURRENT_CALLS) {
 | 
			
		||||
                const RadioCall* calls =
 | 
			
		||||
                    gbinder_reader_read_hidl_type_vec(&reader,
 | 
			
		||||
                        RadioCall, &count);
 | 
			
		||||
 | 
			
		||||
                if (calls) {
 | 
			
		||||
                    /* Build sorted list */
 | 
			
		||||
                    for (i = 0; i < count; i++) {
 | 
			
		||||
                        list = g_slist_insert_sorted(list,
 | 
			
		||||
                            binder_voicecall_info_new(calls + i),
 | 
			
		||||
                            binder_voicecall_info_compare);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else if (resp == RADIO_RESP_GET_CURRENT_CALLS_1_2) {
 | 
			
		||||
                const RadioCall_1_2* calls =
 | 
			
		||||
                    gbinder_reader_read_hidl_type_vec(&reader,
 | 
			
		||||
                        RadioCall_1_2, &count);
 | 
			
		||||
            if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
 | 
			
		||||
                gsize count = 0;
 | 
			
		||||
                if (resp == RADIO_RESP_GET_CURRENT_CALLS) {
 | 
			
		||||
                    const RadioCall* calls =
 | 
			
		||||
                        gbinder_reader_read_hidl_type_vec(&reader,
 | 
			
		||||
                            RadioCall, &count);
 | 
			
		||||
 | 
			
		||||
                if (calls) {
 | 
			
		||||
                    /* Build sorted list */
 | 
			
		||||
                    for (i = 0; i < count; i++) {
 | 
			
		||||
                        list = g_slist_insert_sorted(list,
 | 
			
		||||
                            binder_voicecall_info_new(&calls[i].base),
 | 
			
		||||
                            binder_voicecall_info_compare);
 | 
			
		||||
                    if (calls) {
 | 
			
		||||
                        /* Build sorted list */
 | 
			
		||||
                        for (i = 0; i < count; i++) {
 | 
			
		||||
                            list = g_slist_insert_sorted(list,
 | 
			
		||||
                                binder_voicecall_info_new(calls + i),
 | 
			
		||||
                                binder_voicecall_info_compare);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (resp == RADIO_RESP_GET_CURRENT_CALLS_1_2) {
 | 
			
		||||
                    const RadioCall_1_2* calls =
 | 
			
		||||
                        gbinder_reader_read_hidl_type_vec(&reader,
 | 
			
		||||
                            RadioCall_1_2, &count);
 | 
			
		||||
 | 
			
		||||
                    if (calls) {
 | 
			
		||||
                        /* Build sorted list */
 | 
			
		||||
                        for (i = 0; i < count; i++) {
 | 
			
		||||
                            list = g_slist_insert_sorted(list,
 | 
			
		||||
                                binder_voicecall_info_new(&calls[i].base),
 | 
			
		||||
                                binder_voicecall_info_compare);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    ofono_error("Unexpected getCurrentCalls response %d", resp);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                ofono_error("Unexpected getCurrentCalls response %d", resp);
 | 
			
		||||
                if ((RADIO_VOICE_RESP)resp == RADIO_VOICE_RESP_GET_CURRENT_CALLS) {
 | 
			
		||||
                    gint32 count = 0;
 | 
			
		||||
                    gbinder_reader_read_int32(&reader, &count);
 | 
			
		||||
                    for (i = 0; i < count; i++) {
 | 
			
		||||
                        list = g_slist_insert_sorted(list,
 | 
			
		||||
                            binder_voicecall_info_new_aidl(&reader),
 | 
			
		||||
                            binder_voicecall_info_compare);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    ofono_error("Unexpected getCurrentCalls response %d", resp);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            /*
 | 
			
		||||
@@ -681,8 +784,11 @@ binder_voicecall_clcc_poll(
 | 
			
		||||
{
 | 
			
		||||
    if (!self->clcc_poll_req) {
 | 
			
		||||
        /* getCurrentCalls(int32 serial); */
 | 
			
		||||
        guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
            RADIO_VOICE_REQ_GET_CURRENT_CALLS :
 | 
			
		||||
            RADIO_REQ_GET_CURRENT_CALLS;
 | 
			
		||||
        RadioRequest* req = radio_request_new2(self->g,
 | 
			
		||||
            RADIO_REQ_GET_CURRENT_CALLS, NULL,
 | 
			
		||||
            code, NULL,
 | 
			
		||||
            binder_voicecall_clcc_poll_cb, NULL, self);
 | 
			
		||||
 | 
			
		||||
        radio_request_set_retry(req, BINDER_RETRY_MS, -1);
 | 
			
		||||
@@ -807,7 +913,10 @@ binder_voicecall_dial_cb(
 | 
			
		||||
 | 
			
		||||
    if (status == RADIO_TX_STATUS_OK) {
 | 
			
		||||
        if (error == RADIO_ERROR_NONE) {
 | 
			
		||||
            if (resp == RADIO_RESP_DIAL) {
 | 
			
		||||
            guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
                RADIO_VOICE_RESP_DIAL :
 | 
			
		||||
                RADIO_RESP_DIAL;
 | 
			
		||||
            if (resp == code) {
 | 
			
		||||
                if (self->cb) {
 | 
			
		||||
                    /*
 | 
			
		||||
                     * CLCC will update the oFono call list with
 | 
			
		||||
@@ -907,6 +1016,8 @@ binder_voicecall_dial(
 | 
			
		||||
    RadioDial* dialInfo;
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
    RadioRequest* req;
 | 
			
		||||
    guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_REQ_DIAL : RADIO_REQ_DIAL;
 | 
			
		||||
 | 
			
		||||
    ofono_info("dialing \"%s\"", phstr);
 | 
			
		||||
    DBG_(self, "%s,%d,0", phstr, clir);
 | 
			
		||||
@@ -926,24 +1037,40 @@ binder_voicecall_dial(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* dial(int32 serial, Dial dialInfo) */
 | 
			
		||||
    req = radio_request_new2(self->g, RADIO_REQ_DIAL, &writer,
 | 
			
		||||
    req = radio_request_new2(self->g, code, &writer,
 | 
			
		||||
        binder_voicecall_dial_cb, NULL, self);
 | 
			
		||||
 | 
			
		||||
    /* Prepare the Dial structure */
 | 
			
		||||
    dialInfo = gbinder_writer_new0(&writer, RadioDial);
 | 
			
		||||
    dialInfo->clir = clir;
 | 
			
		||||
    binder_copy_hidl_string(&writer, &dialInfo->address, phstr);
 | 
			
		||||
    if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
 | 
			
		||||
        /* Prepare the Dial structure */
 | 
			
		||||
        dialInfo = gbinder_writer_new0(&writer, RadioDial);
 | 
			
		||||
        dialInfo->clir = clir;
 | 
			
		||||
        binder_copy_hidl_string(&writer, &dialInfo->address, phstr);
 | 
			
		||||
 | 
			
		||||
    /* Write the parent structure */
 | 
			
		||||
    parent.index = gbinder_writer_append_buffer_object(&writer, dialInfo,
 | 
			
		||||
        sizeof(*dialInfo));
 | 
			
		||||
        /* Write the parent structure */
 | 
			
		||||
        parent.index = gbinder_writer_append_buffer_object(&writer, dialInfo,
 | 
			
		||||
            sizeof(*dialInfo));
 | 
			
		||||
 | 
			
		||||
    /* Write the string data */
 | 
			
		||||
    binder_append_hidl_string_data(&writer, dialInfo, address, parent.index);
 | 
			
		||||
        /* Write the string data */
 | 
			
		||||
        binder_append_hidl_string_data(&writer, dialInfo, address, parent.index);
 | 
			
		||||
 | 
			
		||||
    /* UUS information is empty but we still need to write a buffer */
 | 
			
		||||
    parent.offset = G_STRUCT_OFFSET(RadioDial, uusInfo.data.ptr);
 | 
			
		||||
    gbinder_writer_append_buffer_object_with_parent(&writer, NULL, 0, &parent);
 | 
			
		||||
        /* UUS information is empty but we still need to write a buffer */
 | 
			
		||||
        parent.offset = G_STRUCT_OFFSET(RadioDial, uusInfo.data.ptr);
 | 
			
		||||
        gbinder_writer_append_buffer_object_with_parent(&writer, NULL, 0, &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_string16(&writer, phstr);
 | 
			
		||||
        gbinder_writer_append_int32(&writer, clir);
 | 
			
		||||
        /* UUS information array size */
 | 
			
		||||
        gbinder_writer_append_int32(&writer, 0);
 | 
			
		||||
        /* Overwrite parcelable size */
 | 
			
		||||
        gbinder_writer_overwrite_int32(&writer, initial_size,
 | 
			
		||||
            gbinder_writer_bytes_written(&writer) - initial_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Submit the request */
 | 
			
		||||
    if (radio_request_submit(req)) {
 | 
			
		||||
@@ -977,15 +1104,20 @@ binder_voicecall_submit_hangup_req(
 | 
			
		||||
     * work better.
 | 
			
		||||
     */
 | 
			
		||||
    if (call && call->oc.status == OFONO_CALL_STATUS_INCOMING) {
 | 
			
		||||
        guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
            RADIO_VOICE_REQ_HANGUP_WAITING_OR_BACKGROUND :
 | 
			
		||||
            RADIO_REQ_HANGUP_WAITING_OR_BACKGROUND;
 | 
			
		||||
        /* hangupWaitingOrBackground(int32_t serial) */
 | 
			
		||||
        req = radio_request_new2(self->g,
 | 
			
		||||
            RADIO_REQ_HANGUP_WAITING_OR_BACKGROUND, NULL,
 | 
			
		||||
            code, NULL,
 | 
			
		||||
            binder_voicecall_cbd_complete, binder_voicecall_cbd_destroy, cbd);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* hangup(int32 serial, int32 index) */
 | 
			
		||||
        GBinderWriter writer;
 | 
			
		||||
        guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
            RADIO_VOICE_REQ_HANGUP : RADIO_REQ_HANGUP;
 | 
			
		||||
 | 
			
		||||
        req = radio_request_new2(self->g, RADIO_REQ_HANGUP, &writer,
 | 
			
		||||
        req = radio_request_new2(self->g, code, &writer,
 | 
			
		||||
            binder_voicecall_cbd_complete, binder_voicecall_cbd_destroy, cbd);
 | 
			
		||||
        gbinder_writer_append_int32(&writer, cid);
 | 
			
		||||
    }
 | 
			
		||||
@@ -1201,8 +1333,10 @@ binder_voicecall_call_state_changed_event(
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    BinderVoiceCall* self = user_data;
 | 
			
		||||
    guint32 ind_code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_IND_CALL_STATE_CHANGED : RADIO_IND_CALL_STATE_CHANGED;
 | 
			
		||||
 | 
			
		||||
    GASSERT(code == RADIO_IND_CALL_STATE_CHANGED);
 | 
			
		||||
    GASSERT(code == ind_code);
 | 
			
		||||
 | 
			
		||||
    /* Just need to request the call list again */
 | 
			
		||||
    binder_voicecall_clcc_poll(self);
 | 
			
		||||
@@ -1252,27 +1386,62 @@ binder_voicecall_supp_svc_notification(
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_copy(&reader, args);
 | 
			
		||||
    ssn = gbinder_reader_read_hidl_struct(&reader, RadioSuppSvcNotification);
 | 
			
		||||
    if (ssn) {
 | 
			
		||||
        if (ssn->isMT) {
 | 
			
		||||
            struct ofono_phone_number ph;
 | 
			
		||||
    if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
 | 
			
		||||
        ssn = gbinder_reader_read_hidl_struct(&reader, RadioSuppSvcNotification);
 | 
			
		||||
        if (ssn) {
 | 
			
		||||
            if (ssn->isMT) {
 | 
			
		||||
                struct ofono_phone_number ph;
 | 
			
		||||
 | 
			
		||||
            /* MT unsolicited result code */
 | 
			
		||||
            DBG_(self, "MT code: %d, index: %d type: %d number: %s", ssn->code,
 | 
			
		||||
                 ssn->index, ssn->type, ssn->number.data.str);
 | 
			
		||||
            if (ssn->number.data.str && ssn->number.len) {
 | 
			
		||||
                ph.type = ssn->type;
 | 
			
		||||
                g_strlcpy(ph.number, ssn->number.data.str, sizeof(ph.number));
 | 
			
		||||
                /* MT unsolicited result code */
 | 
			
		||||
                DBG_(self, "MT code: %d, index: %d type: %d number: %s", ssn->code,
 | 
			
		||||
                     ssn->index, ssn->type, ssn->number.data.str);
 | 
			
		||||
                if (ssn->number.data.str && ssn->number.len) {
 | 
			
		||||
                    ph.type = ssn->type;
 | 
			
		||||
                    g_strlcpy(ph.number, ssn->number.data.str, sizeof(ph.number));
 | 
			
		||||
                } else {
 | 
			
		||||
                    ph.type = OFONO_NUMBER_TYPE_UNKNOWN;
 | 
			
		||||
                    ph.number[0] = 0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ofono_voicecall_ssn_mt_notify(self->vc, 0, ssn->code,
 | 
			
		||||
                    ssn->index, &ph);
 | 
			
		||||
            } else {
 | 
			
		||||
                ph.type = OFONO_NUMBER_TYPE_UNKNOWN;
 | 
			
		||||
                ph.number[0] = 0;
 | 
			
		||||
                /* MO intermediate result code */
 | 
			
		||||
                ofono_voicecall_ssn_mo_notify(self->vc, 0, ssn->code, ssn->index);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (binder_read_parcelable_size(&reader)) {
 | 
			
		||||
            gboolean is_mt;
 | 
			
		||||
            gint32 code, index, type;
 | 
			
		||||
            char* number;
 | 
			
		||||
 | 
			
		||||
            ofono_voicecall_ssn_mt_notify(self->vc, 0, ssn->code,
 | 
			
		||||
                ssn->index, &ph);
 | 
			
		||||
        } else {
 | 
			
		||||
            /* MO intermediate result code */
 | 
			
		||||
            ofono_voicecall_ssn_mo_notify(self->vc, 0, ssn->code, ssn->index);
 | 
			
		||||
            gbinder_reader_read_bool(&reader, &is_mt);
 | 
			
		||||
            gbinder_reader_read_int32(&reader, &code);
 | 
			
		||||
            gbinder_reader_read_int32(&reader, &index);
 | 
			
		||||
            gbinder_reader_read_int32(&reader, &type);
 | 
			
		||||
            number = gbinder_reader_read_string16(&reader);
 | 
			
		||||
            if (is_mt) {
 | 
			
		||||
                struct ofono_phone_number ph;
 | 
			
		||||
 | 
			
		||||
                /* MT unsolicited result code */
 | 
			
		||||
                DBG_(self, "MT code: %d, index: %d type: %d number: %s", code,
 | 
			
		||||
                     index, type, number);
 | 
			
		||||
                if (number && strlen(number)) {
 | 
			
		||||
                    ph.type = type;
 | 
			
		||||
                    g_strlcpy(ph.number, number, sizeof(ph.number));
 | 
			
		||||
                } else {
 | 
			
		||||
                    ph.type = OFONO_NUMBER_TYPE_UNKNOWN;
 | 
			
		||||
                    ph.number[0] = 0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ofono_voicecall_ssn_mt_notify(self->vc, 0, code,
 | 
			
		||||
                    index, &ph);
 | 
			
		||||
            } else {
 | 
			
		||||
                /* MO intermediate result code */
 | 
			
		||||
                ofono_voicecall_ssn_mo_notify(self->vc, 0, code, index);
 | 
			
		||||
            }
 | 
			
		||||
            g_free(number);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1320,7 +1489,9 @@ binder_voicecall_answer(
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Default action */
 | 
			
		||||
        DBG_(self, "answering current call");
 | 
			
		||||
        binder_voicecall_request_submit(self, RADIO_REQ_ACCEPT_CALL, cbd);
 | 
			
		||||
        guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
            RADIO_VOICE_REQ_ACCEPT_CALL : RADIO_REQ_ACCEPT_CALL;
 | 
			
		||||
        binder_voicecall_request_submit(self, code, cbd);
 | 
			
		||||
    }
 | 
			
		||||
    binder_voicecall_cbd_unref(cbd);
 | 
			
		||||
}
 | 
			
		||||
@@ -1343,7 +1514,9 @@ binder_voicecall_send_dtmf_cb(
 | 
			
		||||
 | 
			
		||||
    if (status == RADIO_TX_STATUS_OK) {
 | 
			
		||||
        if (error == RADIO_ERROR_NONE) {
 | 
			
		||||
            if (resp == RADIO_RESP_SEND_DTMF) {
 | 
			
		||||
            guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
                RADIO_VOICE_RESP_SEND_DTMF : RADIO_RESP_SEND_DTMF;
 | 
			
		||||
            if (resp == code) {
 | 
			
		||||
                /* Send the next one */
 | 
			
		||||
                binder_voicecall_send_one_dtmf(self);
 | 
			
		||||
                return;
 | 
			
		||||
@@ -1399,11 +1572,17 @@ binder_voicecall_send_one_dtmf(
 | 
			
		||||
        if (!self->ext_send_dtmf_id) {
 | 
			
		||||
            /* sendDtmf(int32 serial, string tones) */
 | 
			
		||||
            GBinderWriter writer;
 | 
			
		||||
            guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
                RADIO_VOICE_REQ_SEND_DTMF : RADIO_REQ_SEND_DTMF;
 | 
			
		||||
            RadioRequest* req = radio_request_new2(self->g,
 | 
			
		||||
                RADIO_REQ_SEND_DTMF, &writer,
 | 
			
		||||
                code, &writer,
 | 
			
		||||
                binder_voicecall_send_dtmf_cb, NULL, self);
 | 
			
		||||
 | 
			
		||||
            gbinder_writer_append_hidl_string_copy(&writer, tone);
 | 
			
		||||
            if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
 | 
			
		||||
                gbinder_writer_append_hidl_string_copy(&writer, tone);
 | 
			
		||||
            } else {
 | 
			
		||||
                gbinder_writer_append_string16(&writer, tone);
 | 
			
		||||
            }
 | 
			
		||||
            if (radio_request_submit(req)) {
 | 
			
		||||
                self->send_dtmf_req = req;
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -1468,7 +1647,8 @@ binder_voicecall_create_multiparty(
 | 
			
		||||
{
 | 
			
		||||
    BinderVoiceCall* self = binder_voicecall_get_data(vc);
 | 
			
		||||
    BinderVoiceCallCbData* cbd = binder_voicecall_cbd_new(self, cb, data);
 | 
			
		||||
    const RADIO_REQ req = RADIO_REQ_CONFERENCE;
 | 
			
		||||
    const guint32 req = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_REQ_CONFERENCE : RADIO_REQ_CONFERENCE;
 | 
			
		||||
 | 
			
		||||
    if (binder_voicecall_have_ext_call(self)) {
 | 
			
		||||
        if (!binder_voicecall_ext_conference(self, cbd)) {
 | 
			
		||||
@@ -1512,7 +1692,9 @@ binder_voicecall_transfer(
 | 
			
		||||
{
 | 
			
		||||
    BinderVoiceCall* self = binder_voicecall_get_data(vc);
 | 
			
		||||
    BinderVoiceCallCbData* cbd = binder_voicecall_cbd_new(self, cb, data);
 | 
			
		||||
    const RADIO_REQ req = RADIO_REQ_EXPLICIT_CALL_TRANSFER;
 | 
			
		||||
    const guint32 req = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_REQ_EXPLICIT_CALL_TRANSFER :
 | 
			
		||||
        RADIO_REQ_EXPLICIT_CALL_TRANSFER;
 | 
			
		||||
 | 
			
		||||
    if (binder_voicecall_have_ext_call(self)) {
 | 
			
		||||
        if (!binder_voicecall_ext_transfer(self, cbd)) {
 | 
			
		||||
@@ -1540,8 +1722,11 @@ binder_voicecall_private_chat(
 | 
			
		||||
 | 
			
		||||
    /* separateConnection(int32 serial, int32 index) */
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
    guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_REQ_SEPARATE_CONNECTION :
 | 
			
		||||
        RADIO_REQ_SEPARATE_CONNECTION;
 | 
			
		||||
    RadioRequest* req = radio_request_new2(self->g,
 | 
			
		||||
        RADIO_REQ_SEPARATE_CONNECTION, &writer,
 | 
			
		||||
        code, &writer,
 | 
			
		||||
        binder_voicecall_cbd_complete, binder_voicecall_cbd_destroy, cbd);
 | 
			
		||||
 | 
			
		||||
    DBG_(self, "Private chat with id %d", cid);
 | 
			
		||||
@@ -1586,12 +1771,12 @@ binder_voicecall_swap_with_fallback(
 | 
			
		||||
 | 
			
		||||
    if (binder_voicecall_have_ext_call(self)) {
 | 
			
		||||
        if (!binder_voicecall_ext_swap(self, cbd, flags)) {
 | 
			
		||||
            DBG_(self, "%s (fallback)", radio_req_name(fallback));
 | 
			
		||||
            DBG_(self, "%s (fallback)", radio_req_name2(self->instance, fallback));
 | 
			
		||||
            binder_voicecall_request_submit(self, fallback, cbd);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Default action */
 | 
			
		||||
        DBG_(self, "%s", radio_req_name(fallback));
 | 
			
		||||
        DBG_(self, "%s", radio_req_name2(self->instance, fallback));
 | 
			
		||||
        binder_voicecall_request_submit(self, fallback, cbd);
 | 
			
		||||
    }
 | 
			
		||||
    binder_voicecall_cbd_unref(cbd);
 | 
			
		||||
@@ -1604,8 +1789,12 @@ binder_voicecall_swap_without_accept(
 | 
			
		||||
    ofono_voicecall_cb_t cb,
 | 
			
		||||
    void* data)
 | 
			
		||||
{
 | 
			
		||||
    BinderVoiceCall* self = binder_voicecall_get_data(vc);
 | 
			
		||||
    guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_REQ_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE :
 | 
			
		||||
        RADIO_REQ_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE;
 | 
			
		||||
    binder_voicecall_swap_with_fallback(vc, BINDER_EXT_CALL_SWAP_NO_FLAGS,
 | 
			
		||||
        RADIO_REQ_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, cb, data);
 | 
			
		||||
        code, cb, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -1615,8 +1804,12 @@ binder_voicecall_hold_all_active(
 | 
			
		||||
    ofono_voicecall_cb_t cb,
 | 
			
		||||
    void* data)
 | 
			
		||||
{
 | 
			
		||||
    BinderVoiceCall* self = binder_voicecall_get_data(vc);
 | 
			
		||||
    guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_REQ_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE :
 | 
			
		||||
        RADIO_REQ_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE;
 | 
			
		||||
    binder_voicecall_swap_with_fallback(vc, BINDER_EXT_CALL_SWAP_NO_FLAGS,
 | 
			
		||||
        RADIO_REQ_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, cb, data);
 | 
			
		||||
        code, cb, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -1626,8 +1819,12 @@ binder_voicecall_release_all_active(
 | 
			
		||||
    ofono_voicecall_cb_t cb,
 | 
			
		||||
    void* data)
 | 
			
		||||
{
 | 
			
		||||
    BinderVoiceCall* self = binder_voicecall_get_data(vc);
 | 
			
		||||
    guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_REQ_HANGUP_FOREGROUND_RESUME_BACKGROUND :
 | 
			
		||||
        RADIO_REQ_HANGUP_FOREGROUND_RESUME_BACKGROUND;
 | 
			
		||||
    binder_voicecall_swap_with_fallback(vc, BINDER_EXT_CALL_SWAP_FLAG_HANGUP,
 | 
			
		||||
        RADIO_REQ_HANGUP_FOREGROUND_RESUME_BACKGROUND, cb, data);
 | 
			
		||||
        code, cb, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -1668,7 +1865,7 @@ binder_voicecall_hangup_with_fallback(
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    DBG_(self, "%s %u", radio_req_name(fallback), id);
 | 
			
		||||
                    DBG_(self, "%s %u", radio_req_name2(self->instance, fallback), id);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* Request wasn't submitted - will use the fallback */
 | 
			
		||||
@@ -1677,11 +1874,11 @@ binder_voicecall_hangup_with_fallback(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (use_fallback || !cbd->pending_call_count) {
 | 
			
		||||
            DBG_(self, "%s", radio_req_name(fallback));
 | 
			
		||||
            DBG_(self, "%s", radio_req_name2(self->instance, fallback));
 | 
			
		||||
            binder_voicecall_request_submit(self, fallback, cbd);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        DBG_(self, "%s", radio_req_name(fallback));
 | 
			
		||||
        DBG_(self, "%s", radio_req_name2(self->instance, fallback));
 | 
			
		||||
        binder_voicecall_request_submit(self, fallback, cbd);
 | 
			
		||||
    }
 | 
			
		||||
    binder_voicecall_cbd_unref(cbd);
 | 
			
		||||
@@ -1695,10 +1892,14 @@ binder_voicecall_release_all_held(
 | 
			
		||||
    void* data)
 | 
			
		||||
{
 | 
			
		||||
    DBG__(vc, "");
 | 
			
		||||
    BinderVoiceCall* self = binder_voicecall_get_data(vc);
 | 
			
		||||
    guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_REQ_HANGUP_WAITING_OR_BACKGROUND :
 | 
			
		||||
        RADIO_REQ_HANGUP_WAITING_OR_BACKGROUND;
 | 
			
		||||
    binder_voicecall_hangup_with_fallback(vc,
 | 
			
		||||
        binder_voicecall_hangup_filter_held,
 | 
			
		||||
        BINDER_EXT_CALL_HANGUP_REJECT,
 | 
			
		||||
        RADIO_REQ_HANGUP_WAITING_OR_BACKGROUND, cb, data);
 | 
			
		||||
        code, cb, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -1709,10 +1910,13 @@ binder_voicecall_set_udub(
 | 
			
		||||
    void* data)
 | 
			
		||||
{
 | 
			
		||||
    DBG__(vc, "");
 | 
			
		||||
    BinderVoiceCall* self = binder_voicecall_get_data(vc);
 | 
			
		||||
    guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
 | 
			
		||||
        RADIO_VOICE_REQ_REJECT_CALL : RADIO_REQ_REJECT_CALL;
 | 
			
		||||
    binder_voicecall_hangup_with_fallback(vc,
 | 
			
		||||
        binder_voicecall_hangup_filter_incoming_waiting,
 | 
			
		||||
        BINDER_EXT_CALL_HANGUP_REJECT,
 | 
			
		||||
        RADIO_REQ_REJECT_CALL, cb, data);
 | 
			
		||||
        code, cb, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -1721,8 +1925,13 @@ binder_voicecall_enable_supp_svc(
 | 
			
		||||
    BinderVoiceCall* self)
 | 
			
		||||
{
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
    RadioRequest* req = radio_request_new2(self->g,
 | 
			
		||||
        RADIO_REQ_SET_SUPP_SERVICE_NOTIFICATIONS, &writer,
 | 
			
		||||
    const RADIO_AIDL_INTERFACE iface_aidl =
 | 
			
		||||
        radio_client_aidl_interface(self->network_client);
 | 
			
		||||
    guint32 code = iface_aidl == RADIO_NETWORK_INTERFACE ?
 | 
			
		||||
        RADIO_NETWORK_REQ_SET_SUPP_SERVICE_NOTIFICATIONS :
 | 
			
		||||
        RADIO_REQ_SET_SUPP_SERVICE_NOTIFICATIONS;
 | 
			
		||||
    RadioRequest* req = radio_request_new(self->network_client,
 | 
			
		||||
        code, &writer,
 | 
			
		||||
        NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
    /* setSuppServiceNotifications(int32 serial, bool enable); */
 | 
			
		||||
@@ -1763,29 +1972,58 @@ binder_voicecall_ecclist_changed(
 | 
			
		||||
{
 | 
			
		||||
    BinderVoiceCall* self = user_data;
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    gsize count = 0;
 | 
			
		||||
    const RadioEmergencyNumber* list;
 | 
			
		||||
    const char** en_list = NULL;
 | 
			
		||||
 | 
			
		||||
    /* currentEmergencyNumberList(RadioIndicationType,vec<EmergencyNumber>); */
 | 
			
		||||
    gbinder_reader_copy(&reader, args);
 | 
			
		||||
    list = gbinder_reader_read_hidl_type_vec(&reader,
 | 
			
		||||
        RadioEmergencyNumber, &count);
 | 
			
		||||
    if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
 | 
			
		||||
        /* currentEmergencyNumberList(RadioIndicationType,vec<EmergencyNumber>); */
 | 
			
		||||
        gsize count = 0;
 | 
			
		||||
        const char** en_list = NULL;
 | 
			
		||||
        const RadioEmergencyNumber* list;
 | 
			
		||||
        list = gbinder_reader_read_hidl_type_vec(&reader,
 | 
			
		||||
            RadioEmergencyNumber, &count);
 | 
			
		||||
 | 
			
		||||
    DBG_(self, "%u emergency number(s)", (guint) count);
 | 
			
		||||
    if (count) {
 | 
			
		||||
        guint i;
 | 
			
		||||
        DBG_(self, "%zu emergency number(s)", count);
 | 
			
		||||
        if (count) {
 | 
			
		||||
            guint i;
 | 
			
		||||
 | 
			
		||||
        en_list = g_new(const char*, count + 1);
 | 
			
		||||
        for (i = 0; i < count; i++) {
 | 
			
		||||
            en_list[i] = list[i].number.data.str;
 | 
			
		||||
            DBG("%s", en_list[i]);
 | 
			
		||||
            en_list = g_new0(const char*, count + 1);
 | 
			
		||||
            for (i = 0; i < count; i++) {
 | 
			
		||||
                en_list[i] = list[i].number.data.str;
 | 
			
		||||
                DBG("%s", en_list[i]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        en_list[i] = NULL;
 | 
			
		||||
    }
 | 
			
		||||
        ofono_voicecall_en_list_notify(self->vc, (char**) en_list);
 | 
			
		||||
        g_free(en_list);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* currentEmergencyNumberList(RadioIndicationType,EmergencyNumber[]); */
 | 
			
		||||
        gint32 count = 0;
 | 
			
		||||
        gbinder_reader_read_int32(&reader, &count);
 | 
			
		||||
        char** en_list = NULL;
 | 
			
		||||
 | 
			
		||||
    ofono_voicecall_en_list_notify(self->vc, (char**) en_list);
 | 
			
		||||
    g_free(en_list);
 | 
			
		||||
        DBG_(self, "%zu emergency number(s)", count);
 | 
			
		||||
        if (count) {
 | 
			
		||||
            guint i;
 | 
			
		||||
 | 
			
		||||
            en_list = g_new0(char*, count + 1);
 | 
			
		||||
            for (i = 0; i < count; i++) {
 | 
			
		||||
                gsize data_read;
 | 
			
		||||
                gsize parcel_size = binder_read_parcelable_size(&reader);
 | 
			
		||||
                gsize initial_size = gbinder_reader_bytes_read(&reader);
 | 
			
		||||
 | 
			
		||||
                en_list[i] = gbinder_reader_read_string16(&reader);
 | 
			
		||||
 | 
			
		||||
                // Ignore rest of values for now
 | 
			
		||||
                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("%s", en_list[i]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        ofono_voicecall_en_list_notify(self->vc, (char**) en_list);
 | 
			
		||||
        g_strfreev(en_list);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -1858,33 +2096,59 @@ binder_voicecall_register(
 | 
			
		||||
    /* Request supplementary service notifications*/
 | 
			
		||||
    binder_voicecall_enable_supp_svc(self);
 | 
			
		||||
 | 
			
		||||
    /* Unsol when call state changes */
 | 
			
		||||
    self->radio_event[VOICECALL_EVENT_CALL_STATE_CHANGED] =
 | 
			
		||||
        radio_client_add_indication_handler(client,
 | 
			
		||||
            RADIO_IND_CALL_STATE_CHANGED,
 | 
			
		||||
            binder_voicecall_call_state_changed_event, self);
 | 
			
		||||
    if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
 | 
			
		||||
        /* Unsol when call state changes */
 | 
			
		||||
        self->radio_event[VOICECALL_EVENT_CALL_STATE_CHANGED] =
 | 
			
		||||
            radio_client_add_indication_handler(client,
 | 
			
		||||
                RADIO_IND_CALL_STATE_CHANGED,
 | 
			
		||||
                binder_voicecall_call_state_changed_event, self);
 | 
			
		||||
 | 
			
		||||
    /* Unsol when call set in hold */
 | 
			
		||||
    self->radio_event[VOICECALL_EVENT_SUPP_SVC_NOTIFICATION] =
 | 
			
		||||
        radio_client_add_indication_handler(client,
 | 
			
		||||
            RADIO_IND_SUPP_SVC_NOTIFY,
 | 
			
		||||
            binder_voicecall_supp_svc_notification, self);
 | 
			
		||||
        /* Unsol when call set in hold */
 | 
			
		||||
        self->radio_event[VOICECALL_EVENT_SUPP_SVC_NOTIFICATION] =
 | 
			
		||||
            radio_client_add_indication_handler(client,
 | 
			
		||||
                RADIO_IND_SUPP_SVC_NOTIFY,
 | 
			
		||||
                binder_voicecall_supp_svc_notification, self);
 | 
			
		||||
 | 
			
		||||
    /* Register for ringback tone notifications */
 | 
			
		||||
    self->radio_event[VOICECALL_EVENT_RINGBACK_TONE] =
 | 
			
		||||
        radio_client_add_indication_handler(client,
 | 
			
		||||
            RADIO_IND_INDICATE_RINGBACK_TONE,
 | 
			
		||||
            binder_voicecall_ringback_tone_event, self);
 | 
			
		||||
        /* Register for ringback tone notifications */
 | 
			
		||||
        self->radio_event[VOICECALL_EVENT_RINGBACK_TONE] =
 | 
			
		||||
            radio_client_add_indication_handler(client,
 | 
			
		||||
                RADIO_IND_INDICATE_RINGBACK_TONE,
 | 
			
		||||
                binder_voicecall_ringback_tone_event, self);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * This one is IRadio 1.4 specific and we won't actually receive
 | 
			
		||||
     * it unless IRadio 1.4 is actually in use. It's OK to register
 | 
			
		||||
     * the handler unconditionally, though.
 | 
			
		||||
     */
 | 
			
		||||
    self->radio_event[VOICECALL_EVENT_ECCLIST_CHANGED] =
 | 
			
		||||
        radio_client_add_indication_handler(client,
 | 
			
		||||
            RADIO_IND_CURRENT_EMERGENCY_NUMBER_LIST,
 | 
			
		||||
            binder_voicecall_ecclist_changed, self);
 | 
			
		||||
        /*
 | 
			
		||||
         * This one is IRadio 1.4 specific and we won't actually receive
 | 
			
		||||
         * it unless IRadio 1.4 is actually in use. It's OK to register
 | 
			
		||||
         * the handler unconditionally, though.
 | 
			
		||||
         */
 | 
			
		||||
        self->radio_event[VOICECALL_EVENT_ECCLIST_CHANGED] =
 | 
			
		||||
            radio_client_add_indication_handler(client,
 | 
			
		||||
                RADIO_IND_CURRENT_EMERGENCY_NUMBER_LIST,
 | 
			
		||||
                binder_voicecall_ecclist_changed, self);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Unsol when call state changes */
 | 
			
		||||
        self->radio_event[VOICECALL_EVENT_CALL_STATE_CHANGED] =
 | 
			
		||||
            radio_client_add_indication_handler(client,
 | 
			
		||||
                RADIO_VOICE_IND_CALL_STATE_CHANGED,
 | 
			
		||||
                binder_voicecall_call_state_changed_event, self);
 | 
			
		||||
 | 
			
		||||
        /* Unsol when call set in hold */
 | 
			
		||||
        self->radio_event[VOICECALL_EVENT_SUPP_SVC_NOTIFICATION] =
 | 
			
		||||
            radio_client_add_indication_handler(self->network_client,
 | 
			
		||||
                RADIO_NETWORK_IND_SUPP_SVC_NOTIFY,
 | 
			
		||||
                binder_voicecall_supp_svc_notification, self);
 | 
			
		||||
 | 
			
		||||
        /* Register for ringback tone notifications */
 | 
			
		||||
        self->radio_event[VOICECALL_EVENT_RINGBACK_TONE] =
 | 
			
		||||
            radio_client_add_indication_handler(client,
 | 
			
		||||
                RADIO_VOICE_IND_INDICATE_RINGBACK_TONE,
 | 
			
		||||
                binder_voicecall_ringback_tone_event, self);
 | 
			
		||||
 | 
			
		||||
        /* Register for emergency number list notifications */
 | 
			
		||||
        self->radio_event[VOICECALL_EVENT_ECCLIST_CHANGED] =
 | 
			
		||||
            radio_client_add_indication_handler(client,
 | 
			
		||||
                RADIO_VOICE_IND_CURRENT_EMERGENCY_NUMBER_LIST,
 | 
			
		||||
                binder_voicecall_ecclist_changed, self);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Register extension event handlers if there is an extension */
 | 
			
		||||
    if (self->ext) {
 | 
			
		||||
@@ -1916,7 +2180,10 @@ binder_voicecall_probe(
 | 
			
		||||
 | 
			
		||||
    self->vc = vc;
 | 
			
		||||
    self->dtmf_queue = gutil_ring_new();
 | 
			
		||||
    self->g = radio_request_group_new(modem->client); /* Keeps ref to client */
 | 
			
		||||
    self->instance = radio_instance_ref(modem->instance);
 | 
			
		||||
    self->g = radio_request_group_new(modem->voice_client); /* Keeps ref to client */
 | 
			
		||||
    self->network_client = radio_client_ref(modem->network_client);
 | 
			
		||||
    self->interface_aidl = radio_client_aidl_interface(modem->voice_client);
 | 
			
		||||
    self->local_hangup_reasons = gutil_ints_ref(cfg->local_hangup_reasons);
 | 
			
		||||
    self->remote_hangup_reasons = gutil_ints_ref(cfg->remote_hangup_reasons);
 | 
			
		||||
    self->local_release_ids = gutil_int_array_new();
 | 
			
		||||
@@ -1951,6 +2218,8 @@ binder_voicecall_remove(
 | 
			
		||||
    radio_client_remove_all_handlers(self->g->client, self->radio_event);
 | 
			
		||||
    radio_request_group_cancel(self->g);
 | 
			
		||||
    radio_request_group_unref(self->g);
 | 
			
		||||
    radio_client_unref(self->network_client);
 | 
			
		||||
    radio_instance_unref(self->instance);
 | 
			
		||||
 | 
			
		||||
    gutil_ring_unref(self->dtmf_queue);
 | 
			
		||||
    gutil_ints_unref(self->local_hangup_reasons);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user