* Copyright (C) 2023 Xiaomi Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "tapi_cbs.h"
#include "tapi_internal.h"
static bool proxy_get_bool(GDBusProxy* proxy, const char* property)
{
dbus_bool_t value;
if (!g_dbus_proxy_get_property_basic(proxy, property, &value)) {
tapi_log_error("get property fail in %s", __func__);
return false;
}
return value;
}
static int unsol_cbs_message(DBusConnection* connection,
DBusMessage* message, void* user_data)
{
const char* member;
DBusMessageIter iter, list;
DBusMessageIter entry, result;
char* text;
tapi_async_handler* handler = user_data;
tapi_async_result* ar;
tapi_async_function cb;
char *name, *value;
dbus_bool_t value_t = false;
tapi_cbs_message* cbs_message;
if (NULL == handler) {
tapi_log_debug("handler in %s is null", __func__);
return 0;
}
ar = handler->result;
if (ar == NULL) {
tapi_log_debug("async result in %s is null", __func__);
return 0;
}
cb = handler->cb_function;
if (cb == NULL) {
tapi_log_debug("callback in %s is null", __func__);
return 0;
}
if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) {
tapi_log_error("message type is not signal in %s", __func__);
return 0;
}
if (!dbus_message_iter_init(message, &iter)) {
tapi_log_error("message iter init fail in %s", __func__);
return 0;
}
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
tapi_log_error("message iter type is not string in %s", __func__);
return 0;
}
dbus_message_iter_get_basic(&iter, &text);
member = dbus_message_get_member(message);
if (strcmp(member, "IncomingBroadcast") == 0) {
cbs_message = calloc(1, sizeof(tapi_cbs_message));
if (cbs_message == NULL) {
tapi_log_error("cbs_message in %s is null", __func__);
return 0;
}
cbs_message->text = text;
dbus_message_iter_next(&iter);
dbus_message_iter_get_basic(&iter, &cbs_message->channel);
ar->data = cbs_message;
ar->status = OK;
cb(ar);
free(cbs_message);
} else if (strcmp(member, "EmergencyBroadcast") == 0) {
tapi_cbs_emergency_message* cbs_emergency_message = calloc(1, sizeof(tapi_cbs_emergency_message));
if (cbs_emergency_message == NULL) {
tapi_log_error("cbs_emergency_message in %s is null", __func__);
return 0;
}
cbs_emergency_message->text = text;
dbus_message_iter_next(&iter);
dbus_message_iter_recurse(&iter, &list);
while (dbus_message_iter_get_arg_type(&list) == DBUS_TYPE_DICT_ENTRY) {
dbus_message_iter_recurse(&list, &entry);
dbus_message_iter_get_basic(&entry, &name);
dbus_message_iter_next(&entry);
dbus_message_iter_recurse(&entry, &result);
dbus_message_iter_get_basic(&result, &value);
if (strcmp(name, "EmergencyType") == 0) {
dbus_message_iter_get_basic(&result, &cbs_emergency_message->emergency_type);
} else if (strcmp(name, "EmergencyAlert") == 0) {
dbus_message_iter_get_basic(&result, &value_t);
cbs_emergency_message->emergency_alert = value_t;
} else if (strcmp(name, "Popup") == 0) {
dbus_message_iter_get_basic(&result, &value_t);
cbs_emergency_message->popup = value_t;
}
dbus_message_iter_next(&list);
}
ar->data = cbs_emergency_message;
ar->status = OK;
cb(ar);
free(cbs_emergency_message);
}
return 1;
}
int tapi_sms_set_cell_broadcast_power_on(tapi_context context, int slot_id, bool state)
{
dbus_context* ctx = context;
dbus_bool_t cbs_state = state;
GDBusProxy* proxy;
if (ctx == NULL) {
tapi_log_error("context in %s is null", __func__);
return -EINVAL;
}
if (!tapi_is_valid_slotid(slot_id)) {
tapi_log_error("invalid slot id in %s", __func__);
return -EINVAL;
}
if (!ctx->client_ready) {
tapi_log_error("dbus client is not ready in %s", __func__);
return -EAGAIN;
}
proxy = get_dbus_proxy_by_type(ctx, slot_id, DBUS_PROXY_CBS);
if (proxy == NULL) {
tapi_log_error("no available proxy in %s", __func__);
return -EIO;
}
if (!g_dbus_proxy_set_property_basic(proxy, "Powered",
DBUS_TYPE_BOOLEAN, &cbs_state, NULL, NULL, NULL)) {
tapi_log_error("set property failed in %s", __func__);
return -EINVAL;
}
return OK;
}
int tapi_sms_get_cell_broadcast_power_on(tapi_context context, int slot_id, bool* state)
{
dbus_context* ctx = context;
GDBusProxy* proxy;
if (ctx == NULL) {
tapi_log_error("context in %s is null", __func__);
return -EINVAL;
}
if (!tapi_is_valid_slotid(slot_id)) {
tapi_log_error("invalid slot id in %s", __func__);
return -EINVAL;
}
proxy = get_dbus_proxy_by_type(ctx, slot_id, DBUS_PROXY_CBS);
if (proxy == NULL) {
tapi_log_error("no available proxy in %s", __func__);
return -EIO;
}
*state = proxy_get_bool(proxy, "Powered");
return OK;
}
int tapi_sms_set_cell_broadcast_topics(tapi_context context, int slot_id, char* topics)
{
dbus_context* ctx = context;
GDBusProxy* proxy;
if (ctx == NULL) {
tapi_log_error("context in %s is null", __func__);
return -EINVAL;
}
if (!tapi_is_valid_slotid(slot_id)) {
tapi_log_error("invalid slot id in %s", __func__);
return -EINVAL;
}
if (!ctx->client_ready) {
tapi_log_error("dbus client is not ready in %s", __func__);
return -EAGAIN;
}
if (topics == NULL) {
tapi_log_error("topics in %s is null", __func__);
return -EINVAL;
}
proxy = get_dbus_proxy_by_type(ctx, slot_id, DBUS_PROXY_CBS);
if (proxy == NULL) {
tapi_log_error("no available proxy in %s", __func__);
return -EIO;
}
if (!g_dbus_proxy_set_property_basic(proxy, "Topics",
DBUS_TYPE_STRING, &topics, NULL, NULL, NULL)) {
tapi_log_error("set property failed in %s", __func__);
return -EINVAL;
}
return OK;
}
int tapi_sms_get_cell_broadcast_topics(tapi_context context, int slot_id, char** topics)
{
dbus_context* ctx = context;
char* value = NULL;
GDBusProxy* proxy;
if (ctx == NULL || topics == NULL) {
tapi_log_error("context or topics in %s is null", __func__);
return -EINVAL;
}
if (!tapi_is_valid_slotid(slot_id)) {
tapi_log_error("invalid slot id in %s", __func__);
return -EINVAL;
}
proxy = get_dbus_proxy_by_type(ctx, slot_id, DBUS_PROXY_CBS);
if (proxy == NULL) {
tapi_log_error("no available proxy in %s", __func__);
return -EIO;
}
if (!g_dbus_proxy_get_property_basic(proxy, "Topics", &value)) {
tapi_log_error("get property fail in %s", __func__);
return -EINVAL;
}
if (value != NULL) {
*topics = strdup(value);
if (*topics == NULL)
return -EINVAL;
} else {
*topics = NULL;
}
return OK;
}
int tapi_cbs_register(tapi_context context, int slot_id, tapi_indication_msg msg, void* user_obj,
tapi_async_function p_handle)
{
dbus_context* ctx = context;
tapi_async_handler* user_data;
tapi_async_result* ar;
const char* path;
int watch_id = 0;
if (ctx == NULL) {
tapi_log_error("context in %s is null", __func__);
return -EINVAL;
}
if (!tapi_is_valid_slotid(slot_id)) {
tapi_log_error("invalid slot id in %s", __func__);
return -EINVAL;
}
if (msg < MSG_INCOMING_CBS_IND || msg > MSG_EMERGENCY_CBS_IND) {
tapi_log_error("invalid msg_id in %s, msg_id: %d", __func__, (int)msg);
return -EINVAL;
}
path = tapi_utils_get_modem_path(slot_id);
if (path == NULL) {
tapi_log_error("no available modem in %s", __func__);
return -EIO;
}
user_data = calloc(1, sizeof(tapi_async_handler));
if (user_data == NULL) {
tapi_log_error("user_data in %s is null", __func__);
return -ENOMEM;
}
user_data->cb_function = p_handle;
ar = calloc(1, sizeof(tapi_async_result));
if (ar == NULL) {
tapi_log_error("async result in %s is null", __func__);
free(user_data);
return -ENOMEM;
}
user_data->result = ar;
ar->msg_id = msg;
ar->msg_type = INDICATION;
ar->arg1 = slot_id;
ar->user_obj = user_obj;
switch (msg) {
case MSG_INCOMING_CBS_IND:
watch_id = dbus_client_add_signal_watch(ctx->client, OFONO_SERVICE, path,
OFONO_CELL_BROADCAST_INTERFACE, "IncomingBroadcast",
unsol_cbs_message, user_data, handler_free);
break;
case MSG_EMERGENCY_CBS_IND:
watch_id = dbus_client_add_signal_watch(ctx->client, OFONO_SERVICE, path,
OFONO_CELL_BROADCAST_INTERFACE, "EmergencyBroadcast",
unsol_cbs_message, user_data, handler_free);
break;
default:
break;
}
if (watch_id == 0) {
tapi_log_error("add signal watch failed in %s, msg_id: %d", __func__, (int)msg);
handler_free(user_data);
return -EINVAL;
}
return watch_id;
}