mirror of
https://gitlab.com/ubports/development/core/hybris-support/ofono-binder-plugin-ext-qti
synced 2025-11-03 20:45:53 +08:00
Checkpoint: inital impl of qti radio
This now registrers and reports the state to ofono
This commit is contained in:
15
Makefile
15
Makefile
@@ -2,15 +2,18 @@
|
||||
|
||||
.PHONY: clean all debug release
|
||||
|
||||
# Allow building against an oFono variant.
|
||||
OFONO_PKG ?= ofono
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
# ofono.pc adds -export-symbols-regex linker option which doesn't work
|
||||
# ofono.pc adds -export-symbols-regex linker option which doesn't work
|
||||
# on all platforms.
|
||||
#
|
||||
|
||||
LDPKGS = libofonobinderpluginext libgbinder-radio libgbinder libglibutil gobject-2.0 glib-2.0
|
||||
PKGS = ofono $(LDPKGS)
|
||||
PKGS = $(OFONO_PKG) $(LDPKGS)
|
||||
|
||||
#
|
||||
# Default target
|
||||
@@ -36,7 +39,8 @@ SRC = \
|
||||
qti_ext.c \
|
||||
qti_ims.c \
|
||||
qti_plugin.c \
|
||||
qti_slot.c
|
||||
qti_slot.c \
|
||||
qti_radio_ext.c
|
||||
|
||||
#
|
||||
# Directories
|
||||
@@ -125,15 +129,12 @@ $(DEBUG_SO): $(DEBUG_OBJS)
|
||||
|
||||
$(RELEASE_SO): $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $(RELEASE_LIBS) -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
#
|
||||
# Install
|
||||
#
|
||||
|
||||
PLUGINDIR ?= $$(pkg-config ofono --variable=plugindir)
|
||||
PLUGINDIR ?= $$(pkg-config $(OFONO_PKG) --variable=plugindir)
|
||||
ABS_PLUGINDIR := $(shell echo /$(PLUGINDIR) | sed -r 's|/+|/|g')
|
||||
|
||||
INSTALL = install
|
||||
|
||||
136
src/qti_ims.c
136
src/qti_ims.c
@@ -37,15 +37,25 @@
|
||||
|
||||
#include "qti_ims.h"
|
||||
#include "qti_slot.h"
|
||||
#include "qti_radio_ext.h"
|
||||
|
||||
#include <binder_ext_ims_impl.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
|
||||
#include <gutil_macros.h>
|
||||
#include <gutil_log.h>
|
||||
#include <gbinder.h>
|
||||
|
||||
#define DBG(fmt, ...) \
|
||||
gutil_log(GLOG_MODULE_CURRENT, GLOG_LEVEL_ALWAYS, fmt, ##__VA_ARGS__)
|
||||
|
||||
typedef GObjectClass QtiImsClass;
|
||||
typedef struct qti_ims {
|
||||
GObject parent;
|
||||
char* slot;
|
||||
QtiRadioExt* radio_ext;
|
||||
BINDER_EXT_IMS_STATE ims_state;
|
||||
} QtiIms;
|
||||
|
||||
static
|
||||
@@ -70,6 +80,95 @@ enum qti_ims_signal {
|
||||
|
||||
static guint qti_ims_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
typedef struct qti_ims_result_request {
|
||||
BinderExtIms* ext;
|
||||
BinderExtImsResultFunc complete;
|
||||
GDestroyNotify destroy;
|
||||
void* user_data;
|
||||
} QtiImsResultRequest;
|
||||
|
||||
static
|
||||
QtiImsResultRequest*
|
||||
qti_ims_result_request_new(
|
||||
BinderExtIms* ext,
|
||||
BinderExtImsResultFunc complete,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data)
|
||||
{
|
||||
QtiImsResultRequest* req = g_slice_new(QtiImsResultRequest);
|
||||
|
||||
req->ext = binder_ext_ims_ref(ext);
|
||||
req->complete = complete;
|
||||
req->destroy = destroy;
|
||||
req->user_data = user_data;
|
||||
return req;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_ims_result_request_free(
|
||||
QtiImsResultRequest* req)
|
||||
{
|
||||
binder_ext_ims_unref(req->ext);
|
||||
gutil_slice_free(req);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_ims_result_request_complete(
|
||||
QtiRadioExt* radio_ext,
|
||||
int result,
|
||||
void* user_data)
|
||||
{
|
||||
QtiImsResultRequest* req = user_data;
|
||||
|
||||
req->complete(req->ext, result ? BINDER_EXT_IMS_RESULT_ERROR :
|
||||
BINDER_EXT_IMS_RESULT_OK, req->user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_ims_result_request_destroy(
|
||||
gpointer user_data)
|
||||
{
|
||||
QtiImsResultRequest* req = user_data;
|
||||
|
||||
if (req->destroy) {
|
||||
req->destroy(req->user_data);
|
||||
}
|
||||
qti_ims_result_request_free(req);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_ims_reg_status_changed(
|
||||
QtiRadioExt* radio,
|
||||
QTI_RADIO_REG_STATE state,
|
||||
void* user_data)
|
||||
{
|
||||
QtiIms* self = THIS(user_data);
|
||||
BINDER_EXT_IMS_STATE ims_state;
|
||||
|
||||
switch (state) {
|
||||
case QTI_RADIO_REG_STATE_REGISTERING:
|
||||
ims_state = BINDER_EXT_IMS_STATE_REGISTERING;
|
||||
break;
|
||||
case QTI_RADIO_REG_STATE_REGISTERED:
|
||||
ims_state = BINDER_EXT_IMS_STATE_REGISTERED;
|
||||
break;
|
||||
case QTI_RADIO_REG_STATE_NOT_REGISTERED:
|
||||
ims_state = BINDER_EXT_IMS_STATE_NOT_REGISTERED;
|
||||
break;
|
||||
default:
|
||||
ims_state = BINDER_EXT_IMS_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (ims_state != self->ims_state) {
|
||||
self->ims_state = ims_state;
|
||||
g_signal_emit(self, qti_ims_signals[SIGNAL_STATE_CHANGED], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* BinderExtImsInterface
|
||||
*==========================================================================*/
|
||||
@@ -81,11 +180,12 @@ qti_ims_get_state(
|
||||
{
|
||||
QtiIms* self = THIS(ext);
|
||||
|
||||
DBG("%s", self->slot);
|
||||
#pragma message("TODO: return the actual state")
|
||||
return BINDER_EXT_IMS_STATE_UNKNOWN;
|
||||
DBG("%s ims_state=%d", self->slot, self->ims_state);
|
||||
return self->ims_state;
|
||||
}
|
||||
|
||||
// trun BINDER_EXT_IMS_REGISTRATION to QTI
|
||||
|
||||
static
|
||||
guint
|
||||
qti_ims_set_registration(
|
||||
@@ -96,14 +196,22 @@ qti_ims_set_registration(
|
||||
void* user_data)
|
||||
{
|
||||
QtiIms* self = THIS(ext);
|
||||
const gboolean on = (registration != BINDER_EXT_IMS_REGISTRATION_OFF);
|
||||
const gboolean enabled = (registration != BINDER_EXT_IMS_REGISTRATION_OFF);
|
||||
|
||||
DBG("%s %s", self->slot, on ? "on" : "off");
|
||||
if (on) {
|
||||
#pragma message("TODO: turn IMS registration on")
|
||||
QtiImsResultRequest* req = qti_ims_result_request_new(ext,
|
||||
complete, destroy, user_data);
|
||||
guint id = qti_radio_ext_set_reg_state(self->radio_ext,
|
||||
registration,
|
||||
complete ? qti_ims_result_request_complete : NULL,
|
||||
qti_ims_result_request_destroy, req);
|
||||
|
||||
DBG("%s %s", self->slot, enabled ? "on" : "off");
|
||||
if (enabled) {
|
||||
return id;
|
||||
} else {
|
||||
#pragma message("TODO: turn IMS registration off")
|
||||
qti_ims_result_request_free(req);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -154,7 +262,8 @@ qti_ims_iface_init(
|
||||
|
||||
BinderExtIms*
|
||||
qti_ims_new(
|
||||
const char* slot)
|
||||
const char* slot,
|
||||
QtiRadioExt* radio_ext)
|
||||
{
|
||||
QtiIms* self = g_object_new(THIS_TYPE, NULL);
|
||||
|
||||
@@ -163,6 +272,14 @@ qti_ims_new(
|
||||
* on registration state change and emits SIGNAL_STATE_CHANGED.
|
||||
*/
|
||||
self->slot = g_strdup(slot);
|
||||
self->radio_ext = qti_radio_ext_ref(radio_ext);
|
||||
self->ims_state = BINDER_EXT_IMS_STATE_NOT_REGISTERED;
|
||||
|
||||
if (self->radio_ext) {
|
||||
qti_radio_ext_add_ims_reg_status_handler(self->radio_ext,
|
||||
qti_ims_reg_status_changed, self);
|
||||
}
|
||||
|
||||
return BINDER_EXT_IMS(self);
|
||||
}
|
||||
|
||||
@@ -178,6 +295,7 @@ qti_ims_finalize(
|
||||
QtiIms* self = THIS(object);
|
||||
|
||||
g_free(self->slot);
|
||||
qti_radio_ext_unref(self->radio_ext);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,12 @@
|
||||
|
||||
#include <binder_ext_ims.h>
|
||||
|
||||
typedef struct qti_radio_ext QtiRadioExt;
|
||||
|
||||
BinderExtIms*
|
||||
qti_ims_new(
|
||||
const char* slot)
|
||||
const char* slot,
|
||||
QtiRadioExt* radio_ext)
|
||||
G_GNUC_INTERNAL;
|
||||
|
||||
#endif /* QTI_IMS_H */
|
||||
|
||||
720
src/qti_radio_ext.c
Normal file
720
src/qti_radio_ext.c
Normal file
@@ -0,0 +1,720 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - binder based adaptation QTI plugin
|
||||
*
|
||||
* Copyright (C) 2022 Jolla Ltd.
|
||||
* Copyright (C) 2024 TheKit <thekit@disroot.org>
|
||||
*
|
||||
* 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 <glib-object.h>
|
||||
|
||||
#include "qti_radio_ext.h"
|
||||
#include "qti_radio_ext_types.h"
|
||||
|
||||
#include <radio_types.h>
|
||||
#include <binder_ext_ims_impl.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
#include <gbinder.h>
|
||||
|
||||
#include <gutil_idlepool.h>
|
||||
#include <gutil_log.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#define DBG(fmt, ...) \
|
||||
gutil_log(GLOG_MODULE_CURRENT, GLOG_LEVEL_ALWAYS, fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#define QTI_RADIO_CALL_TIMEOUT (3*1000) /* ms */
|
||||
|
||||
typedef GObjectClass QtiRadioExtClass;
|
||||
typedef struct qti_radio_ext {
|
||||
GObject parent;
|
||||
char* slot;
|
||||
GBinderClient* client;
|
||||
GBinderRemoteObject* remote;
|
||||
GBinderLocalObject* response;
|
||||
GBinderLocalObject* indication;
|
||||
GUtilIdlePool* pool;
|
||||
GHashTable* requests;
|
||||
} QtiRadioExt;
|
||||
|
||||
GType qti_radio_ext_get_type() G_GNUC_INTERNAL;
|
||||
G_DEFINE_TYPE(QtiRadioExt, qti_radio_ext, G_TYPE_OBJECT)
|
||||
|
||||
#define THIS_TYPE qti_radio_ext_get_type()
|
||||
#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, QtiRadioExt)
|
||||
#define PARENT_CLASS qti_radio_ext_parent_class
|
||||
#define KEY(serial) GUINT_TO_POINTER(serial)
|
||||
|
||||
typedef struct qti_radio_ext_request QtiRadioExtRequest;
|
||||
|
||||
typedef void (*QtiRadioExtArgWriteFunc)(
|
||||
GBinderWriter* args,
|
||||
va_list va);
|
||||
|
||||
typedef void (*QtiRadioExtRequestHandlerFunc)(
|
||||
QtiRadioExtRequest* req,
|
||||
const GBinderReader* args);
|
||||
|
||||
typedef void (*QtiRadioExtResultFunc)(
|
||||
QtiRadioExt* radio,
|
||||
int result,
|
||||
void* user_data);
|
||||
|
||||
struct qti_radio_ext_request {
|
||||
guint id; /* request id */
|
||||
gulong tx; /* binder transaction id */
|
||||
QtiRadioExt* radio;
|
||||
gint32 response_code;
|
||||
QtiRadioExtRequestHandlerFunc handle_response;
|
||||
void (*free)(QtiRadioExtRequest* req);
|
||||
GDestroyNotify destroy;
|
||||
void* user_data;
|
||||
};
|
||||
|
||||
typedef struct qti_radio_ext_result_request {
|
||||
QtiRadioExtRequest base;
|
||||
QtiRadioExtResultFunc complete;
|
||||
} QtiRadioExtResultRequest;
|
||||
|
||||
enum qti_radio_ext_signal {
|
||||
SIGNAL_IMS_REG_STATUS_CHANGED,
|
||||
SIGNAL_COUNT
|
||||
};
|
||||
|
||||
#define SIGNAL_IMS_REG_STATUS_CHANGED_NAME "qti-radio-ext-ims-reg-status-changed"
|
||||
|
||||
static guint qti_radio_ext_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
static GLogModule qti_radio_ext_binder_log_module = {
|
||||
.max_level = GLOG_LEVEL_VERBOSE,
|
||||
.level = GLOG_LEVEL_VERBOSE,
|
||||
.flags = GLOG_FLAG_HIDE_NAME
|
||||
};
|
||||
|
||||
static GLogModule qti_radio_ext_binder_dump_module = {
|
||||
.parent = &qti_radio_ext_binder_log_module,
|
||||
.max_level = GLOG_LEVEL_VERBOSE,
|
||||
.level = GLOG_LEVEL_INHERIT,
|
||||
.flags = GLOG_FLAG_HIDE_NAME
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_log_notify(
|
||||
struct ofono_debug_desc* desc)
|
||||
{
|
||||
qti_radio_ext_binder_log_module.level = (desc->flags &
|
||||
OFONO_DEBUG_FLAG_PRINT) ? GLOG_LEVEL_VERBOSE : GLOG_LEVEL_INHERIT;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_dump_notify(
|
||||
struct ofono_debug_desc* desc)
|
||||
{
|
||||
qti_radio_ext_binder_dump_module.level = (desc->flags &
|
||||
OFONO_DEBUG_FLAG_PRINT) ? GLOG_LEVEL_VERBOSE : GLOG_LEVEL_INHERIT;
|
||||
}
|
||||
|
||||
static struct ofono_debug_desc logger_trace OFONO_DEBUG_ATTR = {
|
||||
.name = "qti_binder_trace",
|
||||
.flags = OFONO_DEBUG_FLAG_DEFAULT | OFONO_DEBUG_FLAG_HIDE_NAME,
|
||||
.notify = qti_radio_ext_log_notify
|
||||
};
|
||||
|
||||
static struct ofono_debug_desc logger_dump OFONO_DEBUG_ATTR = {
|
||||
.name = "qti_binder_dump",
|
||||
.flags = OFONO_DEBUG_FLAG_DEFAULT | OFONO_DEBUG_FLAG_HIDE_NAME,
|
||||
.notify = qti_radio_ext_dump_notify
|
||||
};
|
||||
|
||||
static
|
||||
guint
|
||||
qti_radio_ext_new_req_id()
|
||||
{
|
||||
static guint last_id = 0;
|
||||
return last_id++;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_log_req(
|
||||
QtiRadioExt* self,
|
||||
guint32 code,
|
||||
guint32 serial)
|
||||
{
|
||||
static const GLogModule* log = &qti_radio_ext_binder_log_module;
|
||||
const int level = GLOG_LEVEL_VERBOSE;
|
||||
const char* name;
|
||||
|
||||
if (!gutil_log_enabled(log, level))
|
||||
return;
|
||||
|
||||
name = qti_radio_ext_req_name(code);
|
||||
|
||||
if (serial) {
|
||||
gutil_log(log, level, "%s< [%08x] %u %s",
|
||||
self->slot, serial, code, name ? name : "???");
|
||||
} else {
|
||||
gutil_log(log, level, "%s< %u %s",
|
||||
self->slot, code, name ? name : "???");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
qti_radio_ext_log_resp(
|
||||
QtiRadioExt* self,
|
||||
guint32 code,
|
||||
guint32 serial)
|
||||
{
|
||||
static const GLogModule* log = &qti_radio_ext_binder_log_module;
|
||||
const int level = GLOG_LEVEL_VERBOSE;
|
||||
const char* name;
|
||||
|
||||
if (!gutil_log_enabled(log, level))
|
||||
return;
|
||||
|
||||
name = qti_radio_ext_resp_name(code);
|
||||
|
||||
gutil_log(log, level, "%s> [%08x] %u %s",
|
||||
self->slot, serial, code, name ? name : "???");
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_log_ind(
|
||||
QtiRadioExt* self,
|
||||
guint32 code)
|
||||
{
|
||||
static const GLogModule* log = &qti_radio_ext_binder_log_module;
|
||||
const int level = GLOG_LEVEL_VERBOSE;
|
||||
const char* name;
|
||||
|
||||
if (!gutil_log_enabled(log, level))
|
||||
return;
|
||||
|
||||
name = qti_radio_ext_ind_name(code);
|
||||
|
||||
gutil_log(log, level, "%s > %u %s", self->slot, code,
|
||||
name ? name : "???");
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_dump_data(
|
||||
const GBinderReader* reader)
|
||||
{
|
||||
static const GLogModule* log = &qti_radio_ext_binder_dump_module;
|
||||
const int level = GLOG_LEVEL_VERBOSE;
|
||||
gsize size;
|
||||
const guint8* data;
|
||||
|
||||
if (!gutil_log_enabled(log, level))
|
||||
return;
|
||||
|
||||
data = gbinder_reader_get_data(reader, &size);
|
||||
gutil_log_dump(log, level, " ", data, size);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_dump_request(
|
||||
GBinderLocalRequest* args)
|
||||
{
|
||||
static const GLogModule* log = &qti_radio_ext_binder_dump_module;
|
||||
const int level = GLOG_LEVEL_VERBOSE;
|
||||
GBinderWriter writer;
|
||||
const guint8* data;
|
||||
gsize size;
|
||||
|
||||
if (!gutil_log_enabled(log, level))
|
||||
return;
|
||||
|
||||
/* Use writer API to fetch the raw data */
|
||||
gbinder_local_request_init_writer(args, &writer);
|
||||
data = gbinder_writer_get_data(&writer, &size);
|
||||
gutil_log_dump(log, level, " ", data, size);
|
||||
}
|
||||
|
||||
static
|
||||
const QtiRadioRegInfo*
|
||||
qti_radio_ext_read_ims_reg_status_info(
|
||||
QtiRadioExt* self,
|
||||
GBinderReader* reader)
|
||||
{
|
||||
const QtiRadioRegInfo* info;
|
||||
|
||||
info = gbinder_reader_read_hidl_struct(reader, QtiRadioRegInfo);
|
||||
if (info) {
|
||||
const char *uri = info->uri.data.str ? info->uri.data.str : "";
|
||||
const char *error_msg = info->error_message.data.str ? info->error_message.data.str : "";
|
||||
|
||||
DBG("%s: QtiRadioRegInfo state:%d radiotech:%d"
|
||||
" error_code:%d\n"
|
||||
" uri:%s error_msg:%s",
|
||||
self->slot,
|
||||
info->state,
|
||||
info->radio_tech,
|
||||
info->error_code,
|
||||
uri, error_msg);
|
||||
|
||||
return info;
|
||||
} else {
|
||||
DBG("%s: failed to parse QtiRadioRegInfo", self->slot);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_handle_ims_reg_status_report(
|
||||
QtiRadioExt* self,
|
||||
const GBinderReader* args)
|
||||
{
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_reader_copy(&reader, args);
|
||||
const QtiRadioRegInfo* info =
|
||||
qti_radio_ext_read_ims_reg_status_info(self, &reader);
|
||||
|
||||
g_signal_emit(self, qti_radio_ext_signals[SIGNAL_IMS_REG_STATUS_CHANGED],
|
||||
0, info->state);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
qti_radio_ext_indication(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
QtiRadioExt* self = THIS(user_data);
|
||||
const char* iface = gbinder_remote_request_interface(req);
|
||||
GBinderReader args;
|
||||
|
||||
gbinder_remote_request_init_reader(req, &args);
|
||||
qti_radio_ext_log_ind(self, code);
|
||||
qti_radio_ext_dump_data(&args);
|
||||
|
||||
if (g_str_equal(iface, QTI_RADIO_INDICATION_1_0)) {
|
||||
switch(code) {
|
||||
case QTI_RADIO_IND_REG_STATE_INDICATION:
|
||||
qti_radio_ext_handle_ims_reg_status_report(self, &args);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gulong
|
||||
qti_radio_ext_add_ims_reg_status_handler(
|
||||
QtiRadioExt* self,
|
||||
QtiRadioExtImsRegStatusFunc handler,
|
||||
void* user_data)
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(handler)) ? g_signal_connect(self,
|
||||
SIGNAL_IMS_REG_STATUS_CHANGED_NAME, G_CALLBACK(handler), user_data) : 0;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
qti_radio_ext_response(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
QtiRadioExt* self = THIS(user_data);
|
||||
const char* iface = gbinder_remote_request_interface(req);
|
||||
GBinderReader reader;
|
||||
guint32 serial = 0;
|
||||
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
|
||||
gbinder_reader_read_uint32(&reader, &serial);
|
||||
qti_radio_ext_log_resp(self, code, serial);
|
||||
qti_radio_ext_dump_data(&reader);
|
||||
|
||||
if (serial) {
|
||||
QtiRadioExtRequest* req = g_hash_table_lookup(self->requests,
|
||||
KEY(serial));
|
||||
|
||||
if (req && req->response_code == code) {
|
||||
g_object_ref(self);
|
||||
if (req->handle_response) {
|
||||
req->handle_response(req, &reader);
|
||||
}
|
||||
g_hash_table_remove(self->requests, KEY(serial));
|
||||
g_object_unref(self);
|
||||
} else {
|
||||
DBG("Unexpected response %s %u", iface, code);
|
||||
*status = GBINDER_STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_result_response(
|
||||
QtiRadioExtRequest* req,
|
||||
const GBinderReader* args)
|
||||
{
|
||||
gint32 result;
|
||||
GBinderReader reader;
|
||||
QtiRadioExt* self = req->radio;
|
||||
QtiRadioExtResultRequest* result_req = G_CAST(req,
|
||||
QtiRadioExtResultRequest, base);
|
||||
|
||||
gbinder_reader_copy(&reader, args);
|
||||
if (!gbinder_reader_read_int32(&reader, &result)) {
|
||||
ofono_warn("Failed to parse response");
|
||||
result = -1;
|
||||
}
|
||||
if (result_req->complete) {
|
||||
result_req->complete(self, result, req->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_request_default_free(
|
||||
QtiRadioExtRequest* req)
|
||||
{
|
||||
if (req->destroy) {
|
||||
req->destroy(req->user_data);
|
||||
}
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_request_destroy(
|
||||
gpointer user_data)
|
||||
{
|
||||
QtiRadioExtRequest* req = user_data;
|
||||
|
||||
gbinder_client_cancel(req->radio->client, req->tx);
|
||||
req->free(req);
|
||||
}
|
||||
|
||||
static
|
||||
gpointer
|
||||
qti_radio_ext_request_alloc(
|
||||
QtiRadioExt* self,
|
||||
gint32 resp,
|
||||
QtiRadioExtRequestHandlerFunc handler,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data,
|
||||
gsize size)
|
||||
{
|
||||
QtiRadioExtRequest* req = g_malloc0(size);
|
||||
|
||||
req->radio = self;
|
||||
req->response_code = resp;
|
||||
req->handle_response = handler;
|
||||
req->id = qti_radio_ext_new_req_id(self);
|
||||
req->free = qti_radio_ext_request_default_free;
|
||||
req->destroy = destroy;
|
||||
req->user_data = user_data;
|
||||
g_hash_table_insert(self->requests, KEY(req->id), req);
|
||||
return req;
|
||||
}
|
||||
|
||||
static
|
||||
QtiRadioExtResultRequest*
|
||||
qti_radio_ext_result_request_new(
|
||||
QtiRadioExt* self,
|
||||
gint32 resp,
|
||||
QtiRadioExtResultFunc complete,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data)
|
||||
{
|
||||
QtiRadioExtResultRequest* req =
|
||||
(QtiRadioExtResultRequest*)qti_radio_ext_request_alloc(self, resp,
|
||||
qti_radio_ext_result_response, destroy, user_data,
|
||||
sizeof(QtiRadioExtResultRequest));
|
||||
|
||||
req->complete = complete;
|
||||
return req;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_request_sent(
|
||||
GBinderClient* client,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
((QtiRadioExtRequest*)user_data)->tx = 0;
|
||||
}
|
||||
|
||||
static
|
||||
gulong
|
||||
qti_radio_ext_call(
|
||||
QtiRadioExt* self,
|
||||
gint32 code,
|
||||
gint32 serial,
|
||||
GBinderLocalRequest* req,
|
||||
GBinderClientReplyFunc reply,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data)
|
||||
{
|
||||
qti_radio_ext_log_req(self, code, serial);
|
||||
qti_radio_ext_dump_request(req);
|
||||
|
||||
return gbinder_client_transact(self->client, code,
|
||||
GBINDER_TX_FLAG_ONEWAY, req, reply, destroy, user_data);
|
||||
}
|
||||
|
||||
static
|
||||
gulong
|
||||
qti_radio_ext_submit_request(
|
||||
QtiRadioExtRequest* request,
|
||||
gint32 code,
|
||||
gint32 serial,
|
||||
GBinderLocalRequest* args)
|
||||
{
|
||||
return (request->tx = qti_radio_ext_call(request->radio,
|
||||
code, serial, args, qti_radio_ext_request_sent, NULL, request));
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
qti_radio_ext_result_request_submit(
|
||||
QtiRadioExt* self,
|
||||
gint32 req_code,
|
||||
gint32 resp_code,
|
||||
QtiRadioExtArgWriteFunc write_args,
|
||||
QtiRadioExtResultFunc complete,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data,
|
||||
...)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderLocalRequest* args;
|
||||
GBinderWriter writer;
|
||||
QtiRadioExtResultRequest* req =
|
||||
qti_radio_ext_result_request_new(self, resp_code,
|
||||
complete, destroy, user_data);
|
||||
const guint req_id = req->base.id;
|
||||
|
||||
args = gbinder_client_new_request2(self->client, req_code);
|
||||
gbinder_local_request_init_writer(args, &writer);
|
||||
gbinder_writer_append_int32(&writer, req_id);
|
||||
if (write_args) {
|
||||
va_list va;
|
||||
|
||||
va_start(va, user_data);
|
||||
write_args(&writer, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
/* Submit the request */
|
||||
qti_radio_ext_submit_request(&req->base, req_code, req_id, args);
|
||||
gbinder_local_request_unref(args);
|
||||
if (req->base.tx) {
|
||||
/* Success */
|
||||
return req_id;
|
||||
}
|
||||
g_hash_table_remove(self->requests, KEY(req_id));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
QtiRadioExt*
|
||||
qti_radio_ext_create(
|
||||
GBinderServiceManager* sm,
|
||||
GBinderRemoteObject* remote,
|
||||
const char* slot)
|
||||
{
|
||||
QtiRadioExt* self = g_object_new(THIS_TYPE, NULL);
|
||||
const gint code = QTI_RADIO_REQ_SET_CALLBACK;
|
||||
GBinderLocalRequest* req;
|
||||
GBinderWriter writer;
|
||||
int status;
|
||||
|
||||
self->slot = g_strdup(slot);
|
||||
self->client = gbinder_client_new(remote, QTI_RADIO_1_0);
|
||||
self->response = gbinder_servicemanager_new_local_object(sm,
|
||||
QTI_RADIO_RESPONSE_1_0, qti_radio_ext_response, self);
|
||||
self->indication = gbinder_servicemanager_new_local_object(sm,
|
||||
QTI_RADIO_INDICATION_1_0, qti_radio_ext_indication, self);
|
||||
|
||||
req = gbinder_client_new_request2(self->client, code);
|
||||
gbinder_local_request_init_writer(req, &writer);
|
||||
gbinder_writer_append_local_object(&writer, self->response);
|
||||
gbinder_writer_append_local_object(&writer, self->indication);
|
||||
|
||||
qti_radio_ext_log_req(self, code, 0 /*serial*/);
|
||||
qti_radio_ext_dump_request(req);
|
||||
gbinder_remote_reply_unref(gbinder_client_transact_sync_reply(self->client,
|
||||
code, req, &status));
|
||||
|
||||
DBG("setResponseFunctions status %d", status);
|
||||
gbinder_local_request_unref(req);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* API
|
||||
*==========================================================================*/
|
||||
|
||||
|
||||
QtiRadioExt*
|
||||
qti_radio_ext_new(
|
||||
const char* dev,
|
||||
const char* slot)
|
||||
{
|
||||
QtiRadioExt* self = NULL;
|
||||
|
||||
GBinderServiceManager* sm = gbinder_servicemanager_new(dev);
|
||||
if (sm) {
|
||||
char* fqname = g_strconcat(QTI_RADIO_1_0, "/", slot, NULL);
|
||||
GBinderRemoteObject* obj = /* autoreleased */
|
||||
gbinder_servicemanager_get_service_sync(sm, fqname, NULL);
|
||||
|
||||
if (obj) {
|
||||
DBG("Connected to %s", fqname);
|
||||
self = qti_radio_ext_create(sm, obj, slot);
|
||||
} else {
|
||||
DBG("Failed to get %s", fqname);
|
||||
}
|
||||
|
||||
g_free(fqname);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
QtiRadioExt*
|
||||
qti_radio_ext_ref(
|
||||
QtiRadioExt* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(self);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
qti_radio_ext_unref(
|
||||
QtiRadioExt* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(self);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_set_reg_state_args(
|
||||
GBinderWriter* args,
|
||||
va_list va)
|
||||
{
|
||||
gbinder_writer_append_int32(args, va_arg(va, gint32));
|
||||
}
|
||||
|
||||
// BINDER_EXT_IMS_REGISTRATION to QTI_RADIO_REG_STATE
|
||||
static
|
||||
QTI_RADIO_REG_STATE
|
||||
qti_radio_ext_reg_state(
|
||||
BINDER_EXT_IMS_REGISTRATION state)
|
||||
{
|
||||
switch (state) {
|
||||
case BINDER_EXT_IMS_REGISTRATION_ON:
|
||||
return QTI_RADIO_REG_STATE_REGISTERED;
|
||||
case BINDER_EXT_IMS_REGISTRATION_OFF:
|
||||
return QTI_RADIO_REG_STATE_NOT_REGISTERED;
|
||||
default:
|
||||
return QTI_RADIO_REG_STATE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
guint
|
||||
qti_radio_ext_set_reg_state(
|
||||
QtiRadioExt* self,
|
||||
BINDER_EXT_IMS_REGISTRATION state,
|
||||
QtiRadioExtResultFunc complete,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data)
|
||||
{
|
||||
QTI_RADIO_REG_STATE reg_state = qti_radio_ext_reg_state(state);
|
||||
|
||||
DBG("Setting registration state %d", reg_state);
|
||||
|
||||
return qti_radio_ext_result_request_submit(self,
|
||||
QTI_RADIO_REQ_REQ_REG_CHANGE,
|
||||
QTI_RADIO_RESP_REQ_REG_CHANGE,
|
||||
qti_radio_ext_set_reg_state_args,
|
||||
complete, destroy, user_data,
|
||||
reg_state);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
QtiRadioExt* self = THIS(object);
|
||||
|
||||
g_free(self->slot);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_init(
|
||||
QtiRadioExt* self)
|
||||
{
|
||||
self->pool = gutil_idle_pool_new();
|
||||
self->requests = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
|
||||
qti_radio_ext_request_destroy);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
qti_radio_ext_class_init(
|
||||
QtiRadioExtClass* klass)
|
||||
{
|
||||
G_OBJECT_CLASS(klass)->finalize = qti_radio_ext_finalize;
|
||||
qti_radio_ext_signals[SIGNAL_IMS_REG_STATUS_CHANGED] =
|
||||
g_signal_new(SIGNAL_IMS_REG_STATUS_CHANGED_NAME, G_OBJECT_CLASS_TYPE(klass),
|
||||
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE,
|
||||
1, G_TYPE_UINT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
73
src/qti_radio_ext.h
Normal file
73
src/qti_radio_ext.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - binder based adaptation QTI plugin
|
||||
*
|
||||
* Copyright (C) 2024 TheKit <thekit@disroot.org>
|
||||
*
|
||||
* 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 QTI_RADIO_EXT_H
|
||||
#define QTI_RADIO_EXT_H
|
||||
|
||||
#include <radio_types.h>
|
||||
#include <binder_ext_ims_impl.h>
|
||||
|
||||
#include "qti_radio_ext_types.h"
|
||||
|
||||
|
||||
typedef struct qti_radio_ext QtiRadioExt;
|
||||
|
||||
typedef void (*QtiRadioExtResultFunc)(
|
||||
QtiRadioExt* radio,
|
||||
int result,
|
||||
void* user_data);
|
||||
|
||||
typedef void (*QtiRadioExtImsRegStatusFunc)(
|
||||
QtiRadioExt* radio,
|
||||
guint32 status,
|
||||
void* user_data);
|
||||
|
||||
QtiRadioExt*
|
||||
qti_radio_ext_new(
|
||||
const char* dev,
|
||||
const char* slot);
|
||||
|
||||
QtiRadioExt*
|
||||
qti_radio_ext_ref(
|
||||
QtiRadioExt* self);
|
||||
|
||||
void
|
||||
qti_radio_ext_unref(
|
||||
QtiRadioExt* self);
|
||||
|
||||
guint
|
||||
qti_radio_ext_set_reg_state(
|
||||
QtiRadioExt* self,
|
||||
BINDER_EXT_IMS_REGISTRATION state,
|
||||
QtiRadioExtResultFunc complete,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data);
|
||||
|
||||
gulong
|
||||
qti_radio_ext_add_ims_reg_status_handler(
|
||||
QtiRadioExt* self,
|
||||
QtiRadioExtImsRegStatusFunc handler,
|
||||
void* user_data);
|
||||
|
||||
|
||||
#endif /* QTI_RADIO_EXT_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
200
src/qti_radio_ext_types.h
Normal file
200
src/qti_radio_ext_types.h
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - binder based adaptation QTI plugin
|
||||
*
|
||||
* Copyright (C) 2024 TheKit <thekit@disroot.org>
|
||||
*
|
||||
* 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 QTI_RADIO_EXT_TYPES_H
|
||||
#define QTI_RADIO_EXT_TYPES_H
|
||||
|
||||
#define QTI_RADIO_IFACE "IImsRadio"
|
||||
#define QTI_RADIO_RESPONSE_IFACE "IImsRadioResponse"
|
||||
#define QTI_RADIO_INDICATION_IFACE "IImsRadioIndication"
|
||||
#define QTI_RADIO_IFACE_PREFIX "vendor.qti.hardware.radio.ims@"
|
||||
|
||||
#define QTI_RADIO_IFACE_1_0(x) QTI_RADIO_IFACE_PREFIX "1.0::" x
|
||||
#define QTI_RADIO_IFACE_1_1(x) QTI_RADIO_IFACE_PREFIX "1.1::" x
|
||||
#define QTI_RADIO_IFACE_1_2(x) QTI_RADIO_IFACE_PREFIX "1.2::" x
|
||||
|
||||
#define QTI_RADIO_1_0 QTI_RADIO_IFACE_1_0(QTI_RADIO_IFACE)
|
||||
#define QTI_RADIO_1_1 QTI_RADIO_IFACE_1_1(QTI_RADIO_IFACE)
|
||||
#define QTI_RADIO_1_2 QTI_RADIO_IFACE_1_2(QTI_RADIO_IFACE)
|
||||
|
||||
#define QTI_RADIO_RESPONSE_1_0 QTI_RADIO_IFACE_1_0(QTI_RADIO_RESPONSE_IFACE)
|
||||
#define QTI_RADIO_RESPONSE_1_1 QTI_RADIO_IFACE_1_1(QTI_RADIO_RESPONSE_IFACE)
|
||||
#define QTI_RADIO_RESPONSE_1_2 QTI_RADIO_IFACE_1_2(QTI_RADIO_RESPONSE_IFACE)
|
||||
|
||||
#define QTI_RADIO_INDICATION_1_0 QTI_RADIO_IFACE_1_0(QTI_RADIO_INDICATION_IFACE)
|
||||
#define QTI_RADIO_INDICATION_1_1 QTI_RADIO_IFACE_1_1(QTI_RADIO_INDICATION_IFACE)
|
||||
#define QTI_RADIO_INDICATION_1_2 QTI_RADIO_IFACE_1_2(QTI_RADIO_INDICATION_IFACE)
|
||||
|
||||
/*
|
||||
enum RegState : int32_t {
|
||||
REGISTERED,
|
||||
NOT_REGISTERED,
|
||||
REGISTERING,
|
||||
INVALID,
|
||||
};
|
||||
*/
|
||||
|
||||
typedef enum qti_radio_reg_state {
|
||||
QTI_RADIO_REG_STATE_REGISTERED = 0,
|
||||
QTI_RADIO_REG_STATE_NOT_REGISTERED = 1,
|
||||
QTI_RADIO_REG_STATE_REGISTERING = 2,
|
||||
QTI_RADIO_REG_STATE_INVALID = 3,
|
||||
} QTI_RADIO_REG_STATE;
|
||||
|
||||
/*
|
||||
enum StatusType : int32_t {
|
||||
STATUS_DISABLED,
|
||||
STATUS_PARTIALLY_ENABLED,
|
||||
STATUS_ENABLED,
|
||||
STATUS_NOT_SUPPORTED,
|
||||
STATUS_INVALID,
|
||||
};
|
||||
*/
|
||||
|
||||
typedef enum qti_radio_status {
|
||||
QTI_RADIO_STATUS_DISABLED = 0,
|
||||
QTI_RADIO_STATUS_PARTIALLY_ENABLED = 1,
|
||||
QTI_RADIO_STATUS_ENABLED = 2,
|
||||
QTI_RADIO_STATUS_NOT_SUPPORTED = 3,
|
||||
QTI_RADIO_STATUS_INVALID = 4,
|
||||
} QTI_RADIO_STATUS;
|
||||
|
||||
/*
|
||||
enum ServiceClassStatus : int32_t {
|
||||
DISABLED,
|
||||
ENABLED,
|
||||
INVALID,
|
||||
};
|
||||
*/
|
||||
|
||||
typedef enum qti_radio_service_status {
|
||||
QTI_RADIO_SERVICE_STATUS_DISABLED = 0,
|
||||
QTI_RADIO_SERVICE_STATUS_ENABLED = 1,
|
||||
QTI_RADIO_SERVICE_STATUS_INVALID = 2,
|
||||
} QTI_RADIO_SERVICE_STATUS;
|
||||
|
||||
/*
|
||||
|
||||
struct RegistrationInfo {
|
||||
RegState state;
|
||||
uint32_t errorCode;
|
||||
string errorMessage;
|
||||
RadioTechType radioTech;
|
||||
string pAssociatedUris;
|
||||
};
|
||||
*/
|
||||
|
||||
typedef struct qti_radio_reg_info {
|
||||
QTI_RADIO_REG_STATE state RADIO_ALIGNED(4);
|
||||
guint32 error_code RADIO_ALIGNED(4);
|
||||
GBinderHidlString error_message RADIO_ALIGNED(8);
|
||||
guint32 radio_tech RADIO_ALIGNED(4);
|
||||
GBinderHidlString uri RADIO_ALIGNED(8);
|
||||
} QtiRadioRegInfo;
|
||||
|
||||
/* c(req, resp, callName, CALL_NAME) */
|
||||
#define QTI_RADIO_EXT_IMS_CALL_1_0(c) \
|
||||
c(2, 1, dail, DAIL) \
|
||||
c(4, 11, getImsRegistrationState, GET_IMS_REG_STATE) \
|
||||
c(7, 4, requestRegistrationChange, REQ_REG_CHANGE) \
|
||||
c(31, 28, setSuppServiceNotification, SET_SUPP_SVC_NOTIFICATION)
|
||||
|
||||
#define QTI_RADIO_EXT_IMS_CALL_1_1(c) \
|
||||
c(41, 3, hangup_1_1, HANGUP_1_1)
|
||||
|
||||
#define QTI_RADIO_EXT_IMS_CALL_1_2(c) \
|
||||
c(42, 3, hangup_1_2, HANGUP_1_2) \
|
||||
c(43, 37, sendImsSms, SEND_IMS_SMS) \
|
||||
c(1, 1, acknowledgeSms, ACK_SMS)
|
||||
|
||||
typedef enum qti_radio_req {
|
||||
/* vendor.mediatek.hardware.qtiradioex@1.0::IqtiRadioExt */
|
||||
QTI_RADIO_REQ_SET_CALLBACK = 1, /* setCallback */
|
||||
#define QTI_RADIO_REQ_(req,resp,Name,NAME) QTI_RADIO_REQ_##NAME = req,
|
||||
QTI_RADIO_EXT_IMS_CALL_1_0(QTI_RADIO_REQ_)
|
||||
#undef QTI_RADIO_REQ_
|
||||
} QTI_RADIO_REQ;
|
||||
|
||||
typedef enum ims_radio_resp {
|
||||
/* vendor.mediatek.hardware.qtiradioex@3.0::IImsRadioResponse */
|
||||
#define QTI_RADIO_RESP_(req,resp,Name,NAME) QTI_RADIO_RESP_##NAME = resp,
|
||||
QTI_RADIO_EXT_IMS_CALL_1_0(QTI_RADIO_RESP_)
|
||||
#undef QTI_RADIO_RESP_
|
||||
} IMS_RADIO_RESP;
|
||||
|
||||
/* e(code, name, NAME) */
|
||||
#define QTI_RADIO_IND_1_0(e) \
|
||||
e(1, onCallStateChanged, CALL_STATE_INDICATION) \
|
||||
e(2, onRing, RING_INDICATION) \
|
||||
e(3, onRingbackTone, RINGBACK_TONE_INDICATION) \
|
||||
e(4, onRegistrationChanged, REG_STATE_INDICATION) \
|
||||
e(5, onHandover, HANDOVER_INDICATION) \
|
||||
e(6, onServiceStatusChanged, SVC_STATUS_INDICATION)
|
||||
|
||||
typedef enum ims_radio_ind {
|
||||
/* vendor.mediatek.hardware.qtiradioex@3.0::IImsRadioIndication */
|
||||
#define QTI_RADIO_IND_(code, name, NAME) QTI_RADIO_IND_##NAME = code,
|
||||
QTI_RADIO_IND_1_0(QTI_RADIO_IND_)
|
||||
#undef QTI_RADIO_IND_
|
||||
} IMS_RADIO_IND;
|
||||
|
||||
static const char*
|
||||
qti_radio_ext_req_name(
|
||||
guint32 req)
|
||||
{
|
||||
switch (req) {
|
||||
#define QTI_RADIO_REQ_(req, resp, name, NAME) \
|
||||
case QTI_RADIO_REQ_##NAME: return #name;
|
||||
QTI_RADIO_EXT_IMS_CALL_1_0(QTI_RADIO_REQ_)
|
||||
#undef QTI_RADIO_REQ_
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char*
|
||||
qti_radio_ext_resp_name(
|
||||
guint32 resp)
|
||||
{
|
||||
switch (resp) {
|
||||
#define QTI_RADIO_RESP_(req, resp, name, NAME) \
|
||||
case QTI_RADIO_RESP_##NAME: return #name;
|
||||
QTI_RADIO_EXT_IMS_CALL_1_0(QTI_RADIO_RESP_)
|
||||
#undef QTI_RADIO_RESP_
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char*
|
||||
qti_radio_ext_ind_name(
|
||||
guint32 ind)
|
||||
{
|
||||
switch (ind) {
|
||||
#define QTI_RADIO_IND_(code, name, NAME) \
|
||||
case QTI_RADIO_IND_##NAME: return #name;
|
||||
QTI_RADIO_IND_1_0(QTI_RADIO_IND_)
|
||||
#undef QTI_RADIO_IND_
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* QTI_RADIO_EXT_TYPES_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#include "qti_slot.h"
|
||||
#include "qti_ims.h"
|
||||
#include "qti_radio_ext.h"
|
||||
|
||||
#include <binder_ext_slot_impl.h>
|
||||
|
||||
@@ -46,6 +47,7 @@ typedef BinderExtSlotClass QtiSlotClass;
|
||||
typedef struct qti_slot {
|
||||
BinderExtSlot parent;
|
||||
BinderExtIms* ims;
|
||||
QtiRadioExt* radio_ext;
|
||||
} QtiSlot;
|
||||
|
||||
GType qti_slot_get_type() G_GNUC_INTERNAL;
|
||||
@@ -105,8 +107,13 @@ qti_slot_new(
|
||||
{
|
||||
QtiSlot* self = g_object_new(THIS_TYPE, NULL);
|
||||
BinderExtSlot* slot = &self->parent;
|
||||
char* radio_slot = g_strdup_printf("imsradio%d", radio->slot_index);
|
||||
|
||||
self->radio_ext = qti_radio_ext_new(radio->dev, radio_slot);
|
||||
if (self->radio_ext) {
|
||||
self->ims = qti_ims_new(radio_slot, self->radio_ext);
|
||||
}
|
||||
|
||||
self->ims = qti_ims_new(radio->slot);
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user