[gbinder-radio] Implement support for AIDL IRadioModem. JB#61702

This commit is contained in:
Nikita Ukhrenkov
2024-07-08 18:14:16 +03:00
committed by Matti Lehtimäki
parent 453595be28
commit b8917f5985
9 changed files with 500 additions and 161 deletions

View File

@@ -74,6 +74,10 @@ RADIO_INTERFACE
radio_client_interface(
RadioClient* client);
RADIO_AIDL_INTERFACE
radio_client_aidl_interface(
RadioClient* client); /* Since 1.6.0 */
const char*
radio_client_slot(
RadioClient* client);

View File

@@ -38,6 +38,7 @@
#define RADIO_INSTANCE_H
#include <radio_types.h>
#include <radio_modem_types.h>
#include <glib-object.h>
@@ -60,6 +61,9 @@ struct radio_instance {
RADIO_INTERFACE version;
/* Since 1.4.3 */
gboolean connected; /* rilConnected received */
/* Since 1.6.0 */
RADIO_INTERFACE_TYPE interface_type;
RADIO_AIDL_INTERFACE interface_aidl;
};
/* These were introduced in 1.4.3 and then renamed in 1.4.6 */
@@ -156,6 +160,15 @@ radio_instance_new_with_modem_slot_and_version(
int slot_index,
RADIO_INTERFACE version); /* Since 1.2.1 */
RadioInstance*
radio_instance_new_with_modem_slot_version_and_interface(
const char* dev,
const char* name,
const char* modem,
int slot,
RADIO_INTERFACE version,
RADIO_AIDL_INTERFACE aidl_interface); /* Since 1.6.0 */
RadioInstance*
radio_instance_get(
const char* dev,

135
include/radio_modem_types.h Normal file
View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2024 Jollyboys Ltd
*
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation
* are those of the authors and should not be interpreted as representing
* any official policies, either expressed or implied.
*/
#ifndef RADIO_MODEM_TYPES_H
#define RADIO_MODEM_TYPES_H
#include <gbinder_types.h>
G_BEGIN_DECLS
#define RADIO_MODEM_INTERFACE_MAX (RADIO_MODEM_INTERFACE_COUNT - 1)
#define RADIO_MODEM_INSTANCE "default"
#define RADIO_MODEM_IFACE_PREFIX "android.hardware.radio.modem."
#define RADIO_MODEM_IFACE "IRadioModem"
#define RADIO_MODEM_RESPONSE_IFACE "IRadioModemResponse"
#define RADIO_MODEM_INDICATION_IFACE "IRadioModemIndication"
#define RADIO_MODEM RADIO_MODEM_IFACE_PREFIX RADIO_MODEM_IFACE
#define RADIO_MODEM_FQNAME RADIO_MODEM "/" RADIO_MODEM_INSTANCE
#define RADIO_MODEM_RESPONSE RADIO_MODEM_IFACE_PREFIX RADIO_MODEM_RESPONSE_IFACE
#define RADIO_MODEM_INDICATION RADIO_MODEM_IFACE_PREFIX RADIO_MODEM_INDICATION_IFACE
/* Transaction codes */
/* c(req,resp,Name,CALL_NAME) */
#define RADIO_MODEM_CALL_1(c) \
c(1,2,enableModem,ENABLE_MODEM) \
c(2,3,getBasebandVersion,GET_BASEBAND_VERSION) \
c(3,4,getDeviceIdentity,GET_DEVICE_IDENTITY) \
c(4,5,getHardwareConfig,GET_HARDWARE_CONFIG) \
c(5,6,getModemActivityInfo,GET_MODEM_ACTIVITY_INFO) \
c(6,7,getModemStackStatus,GET_MODEM_STACK_STATUS) \
c(7,8,getRadioCapability,GET_RADIO_CAPABILITY) \
c(8,9,nvReadItem,NV_READ_ITEM) \
c(9,10,nvResetConfig,NV_RESET_CONFIG) \
c(10,11,nvWriteCdmaPrl,NV_WRITE_CDMA_PRL) \
c(11,12,nvWriteItem,NV_WRITE_ITEM) \
c(12,13,requestShutdown,REQUEST_SHUTDOWN) \
c(14,14,sendDeviceState,SEND_DEVICE_STATE) \
c(15,15,setRadioCapability,SET_RADIO_CAPABILITY) \
c(16,16,setRadioPower,SET_RADIO_POWER) \
/* i(code,Name,IND_NAME) */
#define RADIO_MODEM_IND_1(i) \
i(1,hardwareConfigChanged,HARDWARE_CONFIG_CHANGED) \
i(2,modemReset,MODEM_RESET) \
i(3,radioCapabilityIndication,RADIO_CAPABILITY_INDICATION) \
i(4,radioStateChanged,RADIO_STATE_CHANGED) \
i(5,rilConnected,RIL_CONNECTED) \
typedef enum radio_modem_req {
RADIO_MODEM_REQ_ANY = 0,
RADIO_MODEM_REQ_NONE = 0,
#define RADIO_MODEM_REQ_(req,resp,Name,NAME) RADIO_MODEM_REQ_##NAME = req,
/* android.hardware.radio.modem.IRadioModem v1 */
RADIO_MODEM_CALL_1(RADIO_MODEM_REQ_)
RADIO_MODEM_REQ_RESPONSE_ACKNOWLEDGEMENT = 13, /* responseAcknowledgement */
RADIO_MODEM_REQ_SET_RESPONSE_FUNCTIONS = 17, /* setResponseFunctions */
RADIO_MODEM_1_REQ_LAST = RADIO_MODEM_REQ_SET_RESPONSE_FUNCTIONS,
#undef RADIO_MODEM_REQ_
} RADIO_MODEM_REQ;
G_STATIC_ASSERT(sizeof(RADIO_MODEM_REQ) == 4);
typedef enum radio_modem_resp {
RADIO_MODEM_RESP_ANY = 0,
RADIO_MODEM_RESP_NONE = 0,
#define RADIO_MODEM_RESP_(req,resp,Name,NAME) RADIO_MODEM_RESP_##NAME = resp,
/* android.hardware.radio.modem.IRadioModemResponse v1 */
RADIO_MODEM_CALL_1(RADIO_MODEM_RESP_)
RADIO_MODEM_RESP_ACKNOWLEDGE_REQUEST = 1, /* acknowledgeRequest */
RADIO_MODEM_1_RESP_LAST = RADIO_MODEM_RESP_SET_RADIO_POWER,
#undef RADIO_MODEM_RESP_
} RADIO_MODEM_RESP;
G_STATIC_ASSERT(sizeof(RADIO_MODEM_RESP) == 4);
typedef enum radio_modem_ind {
RADIO_MODEM_IND_ANY = 0,
RADIO_MODEM_IND_NONE = 0,
#define RADIO_MODEM_IND_(code,Name,NAME) RADIO_MODEM_IND_##NAME = code,
/* android.hardware.radio.modem.IRadioModemIndication v1 */
RADIO_MODEM_IND_1(RADIO_MODEM_IND_)
RADIO_MODEM_1_IND_LAST = RADIO_MODEM_IND_RIL_CONNECTED,
#undef RADIO_MODEM_IND_
} RADIO_MODEM_IND;
G_STATIC_ASSERT(sizeof(RADIO_MODEM_IND) == 4);
G_END_DECLS
#endif /* RADIO_MODEM_TYPES_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -66,6 +66,18 @@ typedef enum radio_interface {
RADIO_INTERFACE_COUNT
} RADIO_INTERFACE; /* Since 1.2.0 */
typedef enum radio_aidl_interface {
RADIO_AIDL_INTERFACE_NONE = -1,
// RADIO_DATA_INTERFACE,
// RADIO_IMS_INTERFACE,
// RADIO_MESSAGING_INTERFACE,
RADIO_MODEM_INTERFACE,
// RADIO_NETWORK_INTERFACE,
// RADIO_SIM_INTERFACE,
// RADIO_VOICE_INTERFACE,
RADIO_AIDL_INTERFACE_COUNT
} RADIO_AIDL_INTERFACE; /* Since 1.6.0 */
typedef enum radio_interface_type {
RADIO_INTERFACE_TYPE_NONE,
RADIO_INTERFACE_TYPE_HIDL,

View File

@@ -45,14 +45,29 @@ const char*
radio_req_name(
RADIO_REQ req);
const char*
radio_req_name2(
RadioInstance* instance,
RADIO_REQ req); /* Since 1.6.0 */
const char*
radio_resp_name(
RADIO_RESP resp);
const char*
radio_resp_name2(
RadioInstance* instance,
RADIO_RESP resp); /* Since 1.6.0 */
const char*
radio_ind_name(
RADIO_IND ind);
const char*
radio_ind_name2(
RadioInstance* instance,
RADIO_IND ind); /* Since 1.6.0 */
RADIO_RESP
radio_req_resp(
RADIO_REQ req)

View File

@@ -180,7 +180,7 @@ radio_client_handle_resp(
gpointer user_data)
{
if (!radio_base_handle_resp(RADIO_BASE(user_data), code, info, reader)) {
const char* name = radio_resp_name(code);
const char* name = radio_resp_name2(instance, code);
/* Most likely this is a response to a cancelled request */
GDEBUG("Ignoring IRadio response [%08x] %u %s", info->serial, code,
@@ -281,6 +281,13 @@ radio_client_interface(
return G_LIKELY(self) ? self->instance->version : RADIO_INTERFACE_NONE;
}
RADIO_AIDL_INTERFACE
radio_client_aidl_interface(
RadioClient* self)
{
return G_LIKELY(self) ? self->instance->interface_aidl : RADIO_AIDL_INTERFACE_NONE;
}
void
radio_client_set_default_timeout(
RadioClient* self,

View File

@@ -660,7 +660,7 @@ radio_config_new_with_version_and_interface_type(
RADIO_INTERFACE_TYPE interface_type)
{
static RadioConfig** instances = NULL;
static const RadioConfigInterfaceDesc* interfaces = NULL;
const RadioConfigInterfaceDesc* interfaces = NULL;
gsize num_interfaces = 0;
const char* binder_device = GBINDER_DEFAULT_HWBINDER;

View File

@@ -156,17 +156,22 @@ G_STATIC_ASSERT(G_N_ELEMENTS(radio_response_ifaces) == RADIO_INTERFACE_COUNT + 1
typedef struct radio_interface_desc {
RADIO_INTERFACE version;
RADIO_AIDL_INTERFACE aidl_interface;
const char* radio_iface;
const char* const* ind_ifaces;
const char* const* resp_ifaces;
gint32 set_response_functions_req;
} RadioInterfaceDesc;
#define RADIO_INTERFACE_INDEX(x) (RADIO_INTERFACE_COUNT - x - 1)
#define RADIO_INTERFACE_DESC(v) \
RADIO_INTERFACE_##v, RADIO_##v, \
RADIO_INTERFACE_##v, \
RADIO_AIDL_INTERFACE_NONE, \
RADIO_##v, \
radio_indication_ifaces + RADIO_INTERFACE_INDEX(RADIO_INTERFACE_##v), \
radio_response_ifaces + RADIO_INTERFACE_INDEX(RADIO_INTERFACE_##v)
radio_response_ifaces + RADIO_INTERFACE_INDEX(RADIO_INTERFACE_##v), \
RADIO_REQ_SET_RESPONSE_FUNCTIONS
static const RadioInterfaceDesc radio_interfaces[] = {
{ RADIO_INTERFACE_DESC(1_5) },
@@ -178,6 +183,32 @@ static const RadioInterfaceDesc radio_interfaces[] = {
};
G_STATIC_ASSERT(G_N_ELEMENTS(radio_interfaces) == RADIO_INTERFACE_COUNT);
static const GBinderClientIfaceInfo radio_aidl_iface_info[] = {
{RADIO_MODEM, RADIO_MODEM_1_REQ_LAST},
};
static const char* const radio_modem_indication_ifaces[] = {
RADIO_MODEM_INDICATION,
NULL
};
static const char* const radio_modem_response_ifaces[] = {
RADIO_MODEM_RESPONSE,
NULL
};
static const RadioInterfaceDesc radio_aidl_interfaces[] = {
{
RADIO_INTERFACE_NONE,
RADIO_MODEM_INTERFACE,
RADIO_MODEM,
radio_modem_indication_ifaces,
radio_modem_response_ifaces,
RADIO_MODEM_REQ_SET_RESPONSE_FUNCTIONS,
}
};
G_STATIC_ASSERT(G_N_ELEMENTS(radio_aidl_interfaces) == RADIO_AIDL_INTERFACE_COUNT);
typedef struct radio_instance_tx {
RadioInstance* instance;
RadioInstanceTxCompleteFunc complete;
@@ -205,7 +236,7 @@ radio_instance_req_quark(
q = GPOINTER_TO_UINT(g_hash_table_lookup(priv->req_quarks, key));
if (!q) {
const char* known = radio_req_name(req);
const char* known = radio_req_name2(self, req);
if (known) {
q = g_quark_from_static_string(known);
@@ -232,7 +263,7 @@ radio_instance_resp_quark(
q = GPOINTER_TO_UINT(g_hash_table_lookup(priv->resp_quarks, key));
if (!q) {
const char* known = radio_resp_name(resp);
const char* known = radio_resp_name2(self, resp);
if (known) {
q = g_quark_from_static_string(known);
@@ -280,7 +311,8 @@ radio_instance_indication(
RadioInstance* self = RADIO_INSTANCE(user_data);
const char* iface = gbinder_remote_request_interface(req);
if (gutil_strv_contains((const GStrV*)radio_indication_ifaces, iface)) {
if (gutil_strv_contains((const GStrV*)radio_indication_ifaces, iface)
|| gutil_strv_contains((const GStrV*)radio_modem_indication_ifaces, iface)) {
GBinderReader reader;
guint type;
@@ -294,6 +326,7 @@ radio_instance_indication(
SIGNAL_OBSERVE_INDICATION_0;
int p = RADIO_OBSERVER_PRIORITY_HIGHEST;
gboolean handled = FALSE;
guint ind_ril_connected = 0;
/* High-priority observers are notified first */
for (; p > RADIO_OBSERVER_PRIORITY_DEFAULT; p--) {
@@ -305,7 +338,14 @@ radio_instance_indication(
}
/* rilConnected is a special case */
if (code == RADIO_IND_RIL_CONNECTED) {
if (self->interface_type == RADIO_INTERFACE_TYPE_HIDL) {
ind_ril_connected = RADIO_IND_RIL_CONNECTED;
} else if (self->interface_type == RADIO_INTERFACE_TYPE_AIDL
&& gutil_strv_contains((const GStrV*)radio_modem_indication_ifaces, iface)) {
ind_ril_connected = RADIO_MODEM_IND_RIL_CONNECTED;
}
if (ind_ril_connected && code == ind_ril_connected) {
if (G_UNLIKELY(self->connected)) {
/* We are only supposed to receive it once */
GWARN("%s received unexpected rilConnected", self->slot);
@@ -360,69 +400,78 @@ radio_instance_response(
{
RadioInstance* self = RADIO_INSTANCE(user_data);
const char* iface = gbinder_remote_request_interface(req);
const RadioResponseInfo* info = NULL;
GBinderReader reader;
gint32 ack_serial = 0;
gbinder_remote_request_init_reader(req, &reader);
if (gutil_strv_contains((const GStrV*)radio_response_ifaces, iface)) {
GBinderReader reader;
/* All these should be one-way transactions */
GASSERT(flags & GBINDER_TX_FLAG_ONEWAY);
gbinder_remote_request_init_reader(req, &reader);
if (code == RADIO_RESP_ACKNOWLEDGE_REQUEST) {
/* oneway acknowledgeRequest(int32_t serial) */
gint32 serial;
GDEBUG("%s %u acknowledgeRequest", iface, code);
if (gbinder_reader_read_int32(&reader, &serial)) {
g_signal_emit(self, radio_instance_signals[SIGNAL_ACK], 0,
serial);
}
gbinder_reader_read_int32(&reader, &ack_serial);
} else {
/* All other responses have RadioResponseInfo */
const RadioResponseInfo* info =
gbinder_reader_read_hidl_struct(&reader, RadioResponseInfo);
if (info) {
const GQuark quark = radio_instance_resp_quark(self, code);
const guint* signals = radio_instance_signals +
SIGNAL_OBSERVE_RESPONSE_0;
int p = RADIO_OBSERVER_PRIORITY_HIGHEST;
gboolean handled = FALSE;
/* High-priority observers are notified first */
for (; p > RADIO_OBSERVER_PRIORITY_DEFAULT; p--) {
if (signals[RADIO_OBSERVER_PRIORITY_INDEX(p)]) {
g_signal_emit(self, signals
[RADIO_OBSERVER_PRIORITY_INDEX(p)],
quark, code, info, &reader);
}
}
/* Then handlers */
g_signal_emit(self, radio_instance_signals
[SIGNAL_HANDLE_RESPONSE],
quark, code, info, &reader, &handled);
/* And then remaining observers in their priority order */
for (; p >= RADIO_OBSERVER_PRIORITY_LOWEST; p--) {
if (signals[RADIO_OBSERVER_PRIORITY_INDEX(p)]) {
g_signal_emit(self, signals
[RADIO_OBSERVER_PRIORITY_INDEX(p)],
quark, code, info, &reader);
}
}
/* Ack unhandled responses */
if (info->type == RADIO_RESP_SOLICITED_ACK_EXP && !handled) {
GDEBUG("ack unhandled response");
radio_instance_ack(self);
}
}
info = gbinder_reader_read_hidl_struct(&reader, RadioResponseInfo);
}
} else if (gutil_strv_contains((const GStrV*)radio_modem_response_ifaces, iface)) {
if (code == RADIO_MODEM_RESP_ACKNOWLEDGE_REQUEST) {
gbinder_reader_read_int32(&reader, &ack_serial);
} else {
/* RadioResponseInfo has the same fields/padding between HIDL and AIDL */
gsize out_size;
info = gbinder_reader_read_parcelable(&reader, &out_size);
GASSERT(out_size >= sizeof(RadioResponseInfo));
}
*status = GBINDER_STATUS_OK;
} else {
GWARN("Unexpected response %s %u", iface, code);
*status = GBINDER_STATUS_FAILED;
return NULL;
}
/* All these should be one-way transactions */
GASSERT(flags & GBINDER_TX_FLAG_ONEWAY);
if (ack_serial) {
GDEBUG("%s %u acknowledgeRequest", iface, code);
g_signal_emit(self, radio_instance_signals[SIGNAL_ACK], 0,
ack_serial);
} else if (info) {
const GQuark quark = radio_instance_resp_quark(self, code);
const guint* signals = radio_instance_signals +
SIGNAL_OBSERVE_RESPONSE_0;
int p = RADIO_OBSERVER_PRIORITY_HIGHEST;
gboolean handled = FALSE;
/* High-priority observers are notified first */
for (; p > RADIO_OBSERVER_PRIORITY_DEFAULT; p--) {
if (signals[RADIO_OBSERVER_PRIORITY_INDEX(p)]) {
g_signal_emit(self, signals
[RADIO_OBSERVER_PRIORITY_INDEX(p)],
quark, code, info, &reader);
}
}
/* Then handlers */
g_signal_emit(self, radio_instance_signals
[SIGNAL_HANDLE_RESPONSE],
quark, code, info, &reader, &handled);
/* And then remaining observers in their priority order */
for (; p >= RADIO_OBSERVER_PRIORITY_LOWEST; p--) {
if (signals[RADIO_OBSERVER_PRIORITY_INDEX(p)]) {
g_signal_emit(self, signals
[RADIO_OBSERVER_PRIORITY_INDEX(p)],
quark, code, info, &reader);
}
}
/* Ack unhandled responses */
if (info->type == RADIO_RESP_SOLICITED_ACK_EXP && !handled) {
GDEBUG("ack unhandled response");
radio_instance_ack(self);
}
}
*status = GBINDER_STATUS_OK;
return NULL;
}
@@ -520,10 +569,9 @@ radio_instance_create_version(
self->modem = priv->modem = g_strdup(modem);
self->slot_index = slot_index;
self->version = desc->version;
self->interface_aidl = desc->aidl_interface;
priv->remote = gbinder_remote_object_ref(remote);
priv->client = gbinder_client_new2(remote,
radio_iface_info, G_N_ELEMENTS(radio_iface_info));
priv->indication = gbinder_servicemanager_new_local_object2(sm,
desc->ind_ifaces, radio_instance_indication, self);
priv->response = gbinder_servicemanager_new_local_object2(sm,
@@ -531,14 +579,27 @@ radio_instance_create_version(
priv->death_id = gbinder_remote_object_add_death_handler(remote,
radio_instance_died, self);
if (desc->version != RADIO_INTERFACE_NONE) {
self->interface_type = RADIO_INTERFACE_TYPE_HIDL;
priv->client = gbinder_client_new2(remote,
radio_iface_info, G_N_ELEMENTS(radio_iface_info));
} else if (desc->aidl_interface != RADIO_AIDL_INTERFACE_NONE) {
self->interface_type = RADIO_INTERFACE_TYPE_AIDL;
priv->client = gbinder_client_new2(remote,
radio_aidl_iface_info + desc->aidl_interface, 1);
gbinder_local_object_set_stability(priv->indication, GBINDER_STABILITY_VINTF);
gbinder_local_object_set_stability(priv->response, GBINDER_STABILITY_VINTF);
}
/* IRadio::setResponseFunctions */
req = gbinder_client_new_request2(priv->client,
RADIO_REQ_SET_RESPONSE_FUNCTIONS);
desc->set_response_functions_req);
gbinder_local_request_init_writer(req, &writer);
gbinder_writer_append_local_object(&writer, priv->response);
gbinder_writer_append_local_object(&writer, priv->indication);
gbinder_remote_reply_unref(gbinder_client_transact_sync_reply(priv->client,
RADIO_REQ_SET_RESPONSE_FUNCTIONS, req, &status));
desc->set_response_functions_req, req, &status));
GVERBOSE_("setResponseFunctions %s status %d", slot, status);
gbinder_local_request_unref(req);
@@ -561,32 +622,47 @@ radio_instance_create(
const char* key,
const char* modem,
int slot_index,
RADIO_INTERFACE max_version)
RADIO_INTERFACE max_version,
RADIO_AIDL_INTERFACE aidl_interface)
{
RadioInstance* self = NULL;
GBinderServiceManager* sm = gbinder_servicemanager_new(dev);
const RadioInterfaceDesc* interfaces = NULL;
gsize num_interfaces = 0;
if (sm) {
guint i;
for (i = 0; i < G_N_ELEMENTS(radio_interfaces) && !self; i++) {
const RadioInterfaceDesc* desc = radio_interfaces + i;
if (desc->version <= max_version) {
char* fqname = g_strconcat(desc->radio_iface, "/", slot, NULL);
GBinderRemoteObject* obj = /* autoreleased */
gbinder_servicemanager_get_service_sync(sm, fqname, NULL);
if (obj) {
GINFO("Connected to %s", fqname);
self = radio_instance_create_version(sm, obj, dev, slot,
key, modem, slot_index, desc);
}
g_free(fqname);
}
}
gbinder_servicemanager_unref(sm);
if (!sm) {
GERR_("Failed to get ServiceManager on %s", dev);
return NULL;
}
if (aidl_interface == RADIO_AIDL_INTERFACE_NONE) {
interfaces = radio_interfaces;
num_interfaces = G_N_ELEMENTS(radio_interfaces);
} else if (aidl_interface > RADIO_AIDL_INTERFACE_NONE
&& aidl_interface < RADIO_AIDL_INTERFACE_COUNT) {
interfaces = radio_aidl_interfaces + aidl_interface;
num_interfaces = 1;
}
for (guint i = 0; i < num_interfaces && !self; i++) {
const RadioInterfaceDesc* desc = interfaces + i;
if (desc->version <= max_version) {
char* fqname = g_strconcat(desc->radio_iface, "/", slot, NULL);
GBinderRemoteObject* obj = /* autoreleased */
gbinder_servicemanager_get_service_sync(sm, fqname, NULL);
if (obj) {
GINFO("Connected to %s", fqname);
self = radio_instance_create_version(sm, obj, dev, slot,
key, modem, slot_index, desc);
}
g_free(fqname);
}
}
gbinder_servicemanager_unref(sm);
return self;
}
@@ -595,9 +671,10 @@ char*
radio_instance_make_key(
const char* dev,
const char* name,
RADIO_INTERFACE version)
RADIO_INTERFACE version,
RADIO_AIDL_INTERFACE aidl_interface)
{
return g_strdup_printf("%s:%s:%d", dev, name, version);
return g_strdup_printf("%s:%s:%d:%d", dev, name, version, aidl_interface);
}
static
@@ -705,7 +782,7 @@ radio_instance_ind_quark(
q = GPOINTER_TO_UINT(g_hash_table_lookup(priv->ind_quarks, key));
if (!q) {
const char* known = radio_ind_name(ind);
const char* known = radio_ind_name2(self, ind);
if (known) {
q = g_quark_from_static_string(known);
@@ -775,9 +852,23 @@ radio_instance_new_with_modem_slot_and_version(
const char* modem,
int slot,
RADIO_INTERFACE version) /* Since 1.2.1 */
{
return radio_instance_new_with_modem_slot_version_and_interface(
dev, name, modem, slot, version, RADIO_AIDL_INTERFACE_NONE);
}
RadioInstance*
radio_instance_new_with_modem_slot_version_and_interface(
const char* dev,
const char* name,
const char* modem,
int slot,
RADIO_INTERFACE version,
RADIO_AIDL_INTERFACE aidl_interface) /* Since 1.6.0 */
{
if (dev && dev[0] && name && name[0]) {
char* key = radio_instance_make_key(dev, name, version);
/* HIDL and AIDL would use different binder devices */
char* key = radio_instance_make_key(dev, name, version, aidl_interface);
RadioInstance* self = NULL;
if (radio_instance_table) {
@@ -787,7 +878,8 @@ radio_instance_new_with_modem_slot_and_version(
g_free(key);
return radio_instance_ref(self);
} else {
self = radio_instance_create(dev, name, key, modem, slot, version);
self = radio_instance_create(dev, name, key, modem, slot, version,
aidl_interface);
if (self) {
if (!radio_instance_table) {
radio_instance_table = g_hash_table_new_full
@@ -830,7 +922,7 @@ radio_instance_get_with_version(
RadioInstance* self = NULL;
if (dev && dev[0] && name && name[0] && radio_instance_table) {
char* key = radio_instance_make_key(dev, name, version);
char* key = radio_instance_make_key(dev, name, version, RADIO_AIDL_INTERFACE_NONE);
self = g_hash_table_lookup(radio_instance_table, key);
g_free(key);
@@ -905,7 +997,7 @@ radio_instance_req_name(
RadioInstance* self,
RADIO_REQ req)
{
const char* known = radio_req_name(req);
const char* known = radio_req_name2(self, req);
if (known) {
return known;
@@ -924,7 +1016,7 @@ radio_instance_resp_name(
RadioInstance* self,
RADIO_RESP resp)
{
const char* known = radio_resp_name(resp);
const char* known = radio_resp_name2(self, resp);
if (known) {
return known;
@@ -943,7 +1035,7 @@ radio_instance_ind_name(
RadioInstance* self,
RADIO_IND ind)
{
const char* known = radio_ind_name(ind);
const char* known = radio_ind_name2(self, ind);
if (known) {
return known;

View File

@@ -35,6 +35,7 @@
*/
#include "radio_util_p.h"
#include "radio_instance.h"
#include "radio_log.h"
GLOG_MODULE_DEFINE("gbinder-radio");
@@ -56,29 +57,50 @@ const char*
radio_req_name(
RADIO_REQ req)
{
switch (req) {
case RADIO_REQ_SET_RESPONSE_FUNCTIONS: return "setResponseFunctions";
case RADIO_REQ_RESPONSE_ACKNOWLEDGEMENT: return "responseAcknowledgement";
return radio_req_name2(NULL, req);
}
const char*
radio_req_name2(
RadioInstance* instance,
RADIO_REQ req)
{
if (!G_LIKELY(instance) || instance->interface_type == RADIO_INTERFACE_TYPE_HIDL) {
switch (req) {
case RADIO_REQ_SET_RESPONSE_FUNCTIONS: return "setResponseFunctions";
case RADIO_REQ_RESPONSE_ACKNOWLEDGEMENT: return "responseAcknowledgement";
#define RADIO_REQ_(req,resp,Name,NAME) \
case RADIO_REQ_##NAME: return #Name;
case RADIO_REQ_##NAME: return #Name;
#define RADIO_REQ__(req,resp,Name,NAME,x) \
case RADIO_REQ_##NAME##x: return #Name #x;
RADIO_CALL_1_0(RADIO_REQ_)
RADIO_CALL_1_1(RADIO_REQ_)
RADIO_CALL_1_2(RADIO_REQ_)
RADIO_CALL_1_3(RADIO_REQ_)
RADIO_CALL_1_4_(RADIO_REQ__)
RADIO_CALL_1_5_(RADIO_REQ__)
case RADIO_REQ_##NAME##x: return #Name #x;
RADIO_CALL_1_0(RADIO_REQ_)
RADIO_CALL_1_1(RADIO_REQ_)
RADIO_CALL_1_2(RADIO_REQ_)
RADIO_CALL_1_3(RADIO_REQ_)
RADIO_CALL_1_4_(RADIO_REQ__)
RADIO_CALL_1_5_(RADIO_REQ__)
#undef RADIO_REQ_
#undef RADIO_REQ__
case RADIO_REQ_START_NETWORK_SCAN_1_2: return "startNetworkScan_1_2";
case RADIO_REQ_SET_INDICATION_FILTER_1_2: return "setIndicationFilter_1_2";
case RADIO_REQ_SETUP_DATA_CALL_1_2: return "setupDataCall_1_2";
case RADIO_REQ_DEACTIVATE_DATA_CALL_1_2: return "deactivateDataCall_1_2";
case RADIO_REQ_SET_INITIAL_ATTACH_APN_1_4: return "setInitialAttachApn_1_4";
case RADIO_REQ_SET_DATA_PROFILE_1_4: return "setDataProfile_1_4";
case RADIO_REQ_ANY:
break;
case RADIO_REQ_START_NETWORK_SCAN_1_2: return "startNetworkScan_1_2";
case RADIO_REQ_SET_INDICATION_FILTER_1_2: return "setIndicationFilter_1_2";
case RADIO_REQ_SETUP_DATA_CALL_1_2: return "setupDataCall_1_2";
case RADIO_REQ_DEACTIVATE_DATA_CALL_1_2: return "deactivateDataCall_1_2";
case RADIO_REQ_SET_INITIAL_ATTACH_APN_1_4: return "setInitialAttachApn_1_4";
case RADIO_REQ_SET_DATA_PROFILE_1_4: return "setDataProfile_1_4";
case RADIO_REQ_ANY:
break;
}
} else if (instance->interface_aidl == RADIO_MODEM_INTERFACE) {
switch ((RADIO_MODEM_REQ)req) {
#define RADIO_MODEM_REQ_(req,resp,Name,NAME) \
case RADIO_MODEM_REQ_##NAME: return #Name;
RADIO_MODEM_CALL_1(RADIO_MODEM_REQ_)
#undef RADIO_MODEM_REQ_
case RADIO_MODEM_REQ_SET_RESPONSE_FUNCTIONS: return "setResponseFunctions";
case RADIO_MODEM_REQ_RESPONSE_ACKNOWLEDGEMENT: return "responseAcknowledgement";
case RADIO_MODEM_REQ_ANY:
break;
}
}
return NULL;
}
@@ -87,48 +109,68 @@ const char*
radio_resp_name(
RADIO_RESP resp)
{
switch (resp) {
case RADIO_RESP_ACKNOWLEDGE_REQUEST: return "acknowledgeRequest";
return radio_resp_name2(NULL, resp);
}
const char*
radio_resp_name2(
RadioInstance* instance,
RADIO_RESP resp)
{
if (!G_LIKELY(instance) || instance->interface_type == RADIO_INTERFACE_TYPE_HIDL) {
switch (resp) {
case RADIO_RESP_ACKNOWLEDGE_REQUEST: return "acknowledgeRequest";
#define RADIO_RESP_(req,resp,Name,NAME) \
case RADIO_RESP_##NAME: return #Name "Response";
case RADIO_RESP_##NAME: return #Name "Response";
#define RADIO_RESP__(req,resp,Name,NAME,x) \
case RADIO_RESP_##NAME##x: return #Name "Response" #x;
RADIO_CALL_1_0(RADIO_RESP_)
RADIO_CALL_1_1(RADIO_RESP_)
RADIO_CALL_1_2(RADIO_RESP_)
RADIO_CALL_1_3(RADIO_RESP_)
RADIO_CALL_1_4_(RADIO_RESP__)
RADIO_CALL_1_5_(RADIO_RESP__)
case RADIO_RESP_##NAME##x: return #Name "Response" #x;
RADIO_CALL_1_0(RADIO_RESP_)
RADIO_CALL_1_1(RADIO_RESP_)
RADIO_CALL_1_2(RADIO_RESP_)
RADIO_CALL_1_3(RADIO_RESP_)
RADIO_CALL_1_4_(RADIO_RESP__)
RADIO_CALL_1_5_(RADIO_RESP__)
#undef RADIO_RESP_
#undef RADIO_RESP__
case RADIO_RESP_GET_CELL_INFO_LIST_1_2:
return "getCellInfoListResponse_1_2";
case RADIO_RESP_GET_ICC_CARD_STATUS_1_2:
return "getIccCardStatusResponse_1_2";
case RADIO_RESP_GET_CURRENT_CALLS_1_2:
return "getCurrentCallsResponse_1_2";
case RADIO_RESP_GET_SIGNAL_STRENGTH_1_2:
return "getSignalStrengthResponse_1_2";
case RADIO_RESP_GET_VOICE_REGISTRATION_STATE_1_2:
return "getVoiceRegistrationStateResponse_1_2";
case RADIO_RESP_GET_DATA_REGISTRATION_STATE_1_2:
return "getDataRegistrationStateResponse_1_2";
case RADIO_RESP_GET_CELL_INFO_LIST_RESPONSE_1_4:
return "getCellInfoListResponse_1_4";
case RADIO_RESP_GET_DATA_REGISTRATION_STATE_RESPONSE_1_4:
return "getDataRegistrationStateResponse_1_4";
case RADIO_RESP_GET_ICC_CARD_STATUS_RESPONSE_1_4:
return "getIccCardStatusResponse_1_4";
case RADIO_RESP_GET_DATA_CALL_LIST_RESPONSE_1_4:
return "getDataCallListResponse_1_4";
case RADIO_RESP_GET_DATA_CALL_LIST_1_5:
return "getDataCallList_1_5";
case RADIO_RESP_GET_CELL_INFO_LIST_1_5:
return "getCellInfoListResponse_1_5";
case RADIO_RESP_GET_ICC_CARD_STATUS_1_5:
return "getIccCardStatus_1_5";
case RADIO_RESP_ANY:
break;
case RADIO_RESP_GET_CELL_INFO_LIST_1_2:
return "getCellInfoListResponse_1_2";
case RADIO_RESP_GET_ICC_CARD_STATUS_1_2:
return "getIccCardStatusResponse_1_2";
case RADIO_RESP_GET_CURRENT_CALLS_1_2:
return "getCurrentCallsResponse_1_2";
case RADIO_RESP_GET_SIGNAL_STRENGTH_1_2:
return "getSignalStrengthResponse_1_2";
case RADIO_RESP_GET_VOICE_REGISTRATION_STATE_1_2:
return "getVoiceRegistrationStateResponse_1_2";
case RADIO_RESP_GET_DATA_REGISTRATION_STATE_1_2:
return "getDataRegistrationStateResponse_1_2";
case RADIO_RESP_GET_CELL_INFO_LIST_RESPONSE_1_4:
return "getCellInfoListResponse_1_4";
case RADIO_RESP_GET_DATA_REGISTRATION_STATE_RESPONSE_1_4:
return "getDataRegistrationStateResponse_1_4";
case RADIO_RESP_GET_ICC_CARD_STATUS_RESPONSE_1_4:
return "getIccCardStatusResponse_1_4";
case RADIO_RESP_GET_DATA_CALL_LIST_RESPONSE_1_4:
return "getDataCallListResponse_1_4";
case RADIO_RESP_GET_DATA_CALL_LIST_1_5:
return "getDataCallList_1_5";
case RADIO_RESP_GET_CELL_INFO_LIST_1_5:
return "getCellInfoListResponse_1_5";
case RADIO_RESP_GET_ICC_CARD_STATUS_1_5:
return "getIccCardStatus_1_5";
case RADIO_RESP_ANY:
break;
}
} else if (instance->interface_aidl == RADIO_MODEM_INTERFACE) {
switch ((RADIO_MODEM_RESP)resp) {
case RADIO_MODEM_RESP_ACKNOWLEDGE_REQUEST: return "acknowledgeRequest";
#define RADIO_MODEM_RESP_(req,resp,Name,NAME) \
case RADIO_MODEM_RESP_##NAME: return #Name "Response";
RADIO_MODEM_CALL_1(RADIO_MODEM_RESP_)
#undef RADIO_MODEM_RESP_
case RADIO_MODEM_RESP_ANY:
break;
}
}
return NULL;
}
@@ -137,17 +179,36 @@ const char*
radio_ind_name(
RADIO_IND ind)
{
switch (ind) {
return radio_ind_name2(NULL, ind);
}
const char*
radio_ind_name2(
RadioInstance* instance,
RADIO_IND ind)
{
if (!G_LIKELY(instance) || instance->interface_type == RADIO_INTERFACE_TYPE_HIDL) {
switch (ind) {
#define RADIO_IND_(code,Name,NAME) \
case RADIO_IND_##NAME: return #Name;
RADIO_EVENT_1_0(RADIO_IND_)
RADIO_EVENT_1_1(RADIO_IND_)
RADIO_EVENT_1_2(RADIO_IND_)
RADIO_EVENT_1_4(RADIO_IND_)
RADIO_EVENT_1_5(RADIO_IND_)
case RADIO_IND_##NAME: return #Name;
RADIO_EVENT_1_0(RADIO_IND_)
RADIO_EVENT_1_1(RADIO_IND_)
RADIO_EVENT_1_2(RADIO_IND_)
RADIO_EVENT_1_4(RADIO_IND_)
RADIO_EVENT_1_5(RADIO_IND_)
#undef RADIO_IND_
case RADIO_IND_ANY:
break;
case RADIO_IND_ANY:
break;
}
} else if (instance->interface_aidl == RADIO_MODEM_INTERFACE) {
switch ((RADIO_MODEM_IND)ind) {
#define RADIO_MODEM_IND_(code,Name,NAME) \
case RADIO_MODEM_IND_##NAME: return #Name;
RADIO_MODEM_IND_1(RADIO_MODEM_IND_)
#undef RADIO_MODEM_IND_
case RADIO_MODEM_IND_ANY:
break;
}
}
return NULL;
}