ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/services/ecall_daemon/src/ecall_daemon_main.c b/marvell/services/ecall_daemon/src/ecall_daemon_main.c
new file mode 100644
index 0000000..5030734
--- /dev/null
+++ b/marvell/services/ecall_daemon/src/ecall_daemon_main.c
@@ -0,0 +1,648 @@
+/******************************************************************************
+*(C) Copyright 2021 ASR MicroElectronics Ltd.
+* All Rights Reserved
+******************************************************************************/
+/*--------------------------------------------------------------------------------------------------------------------
+ * -------------------------------------------------------------------------------------------------------------------
+ *
+ * Filename: ecall_daemon_main.c
+ *
+ * Authors: xz
+ *
+ * Description: Entry Point of ecall daemon
+ *
+ * History:
+ * July 20, 2021 - Initial Version
+ *
+ * Notes:
+ *
+ ******************************************************************************/
+
+#ifndef NO_AUDIO
+
+//#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ecall_daemon.h"
+#include "ril.h"
+#include <cutils/properties.h>
+
+struct ubus_context *ecall_ctx = NULL;
+struct ubus_subscriber ecall_subscriber;
+static struct blob_buf ecall_daemon_blob;
+
+#define ECALL_DAEMON_VERSION "1803L_ecall_daemon_version_2.4_20250225"
+
+const struct blobmsg_policy ecall_daemon_set_mode_policy[] ={
+ [0] = {
+ .name = "ecallMode",
+ .type = BLOBMSG_TYPE_STRING,
+ },
+};
+
+const struct blobmsg_policy ecall_daemon_set_smsNum_policy[] ={
+ [0] = {
+ .name = "smsNum",
+ .type = BLOBMSG_TYPE_STRING,
+ },
+};
+
+const struct blobmsg_policy ecall_daemon_send_msdSms_policy[] ={
+ [0] = {
+ .name = "smsFlag",
+ .type = BLOBMSG_TYPE_INT32,
+ },
+};
+
+const struct blobmsg_policy ecall_daemon_set_ecallTimer_policy[] ={
+ [0] = {
+ .name = "timerName",
+ .type = BLOBMSG_TYPE_STRING,
+ },
+ [1] = {
+ .name = "timerValue",
+ .type = BLOBMSG_TYPE_INT32,
+ },
+};
+
+const struct blobmsg_policy ecall_daemon_get_ecallTimer_policy[] ={
+ [0] = {
+ .name = "timerName",
+ .type = BLOBMSG_TYPE_STRING,
+ },
+};
+
+const struct blobmsg_policy ecall_daemon_set_ecallTestNum_policy[] ={
+ [0] = {
+ .name = "testNumber",
+ .type = BLOBMSG_TYPE_STRING,
+ },
+ [1] = {
+ .name = "reconfigNumber",
+ .type = BLOBMSG_TYPE_STRING,
+ },
+};
+
+const struct blobmsg_policy ecall_daemon_set_ecallMsd_policy[] ={
+ [0] = {
+ .name = "msd",
+ .type = BLOBMSG_TYPE_STRING,
+ },
+};
+
+int ecall_daemon_invoke_noreply(const char *service, const char *method, struct blob_attr *msg)
+{
+ int rc;
+ uint32_t id;
+ struct ubus_request req;
+
+ /* Look up the target object id by the object path */
+ if (ubus_lookup_id(ecall_ctx, service, &id))
+ return -1;
+
+ rc = ubus_invoke_async(ecall_ctx, id, method, msg, &req);
+ if (rc != 0)
+ return -2;
+
+ /* cancel req (on client side) because noreply is needed */
+ ubus_abort_request(ecall_ctx, &req);
+ return 0;
+}
+
+int ecall_daemon_ubus_send_ecallCmd(unsigned int op_id, unsigned int param1)
+{
+ unsigned int length;
+ struct blob_buf outBlob;
+ int ret = 0;
+
+ memset(&outBlob, 0, sizeof(outBlob));
+
+ blob_buf_init(&outBlob, 0);
+ length = sizeof(op_id) + sizeof(param1);
+ blobmsg_add_u32(&outBlob, "length", (unsigned int)length);
+ blobmsg_add_u32(&outBlob, "op", (unsigned int)op_id);
+ blobmsg_add_u32(&outBlob, "param1", (unsigned int)param1);
+ if (ecall_daemon_invoke_noreply("audio_if", "ecall_data_set", outBlob.head) == 0)
+ {
+ ret = 0;
+ ECALL_Log("%s: succeed in sending AUDIO_IF_UBUS_ECALL_DATA_SET\n", __FUNCTION__);
+ }
+ else
+ {
+ ret = -1;
+ ECALL_Log("%s: fail to send AUDIO_IF_UBUS_ECALL_DATA_SET\n", __FUNCTION__);
+ }
+
+ blob_buf_free(&outBlob);
+
+ return ret;
+}
+
+static int ecall_daemon_mode_string_reply(struct ubus_context *ctx, struct ubus_request_data *req, char *str)
+{
+ blob_buf_init(&ecall_daemon_blob, 0);
+ blobmsg_add_string(&ecall_daemon_blob, "ecallMode", str);
+ ubus_send_reply(ctx, req, ecall_daemon_blob.head);
+ return 0;
+}
+
+static int ecall_daemon_smsNum_string_reply(struct ubus_context *ctx, struct ubus_request_data *req, char *str)
+{
+ blob_buf_init(&ecall_daemon_blob, 0);
+ blobmsg_add_string(&ecall_daemon_blob, "smsNum", str);
+ ubus_send_reply(ctx, req, ecall_daemon_blob.head);
+ return 0;
+}
+
+static int ecall_daemon_timerVal_string_reply(struct ubus_context *ctx, struct ubus_request_data *req, char *str)
+{
+ blob_buf_init(&ecall_daemon_blob, 0);
+ blobmsg_add_string(&ecall_daemon_blob, "timerVal", str);
+ ubus_send_reply(ctx, req, ecall_daemon_blob.head);
+ return 0;
+}
+
+static int ecall_daemon_ubus_set_ecallMode(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+ struct blob_attr *tb[ARRAY_SIZE(ecall_daemon_set_mode_policy)];
+ struct blob_attr *cur;
+ char *ecallMode = NULL;
+ int err = 0;
+
+ err = blobmsg_parse(ecall_daemon_set_mode_policy, ARRAY_SIZE(ecall_daemon_set_mode_policy), tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ ECALL_Log("%s: blobmsg_parse table fail\n", __FUNCTION__);
+ return -1;
+ }
+
+ cur = tb[0];
+ if (cur)
+ ecallMode = blobmsg_get_string(cur);
+ else
+ ECALL_Log("%s: missing parameter1\n", __FUNCTION__);
+
+ ECALL_Log("%s: ecallMode=%s\n", __FUNCTION__, ecallMode);
+
+ if (ecallMode != NULL)
+ {
+ err = ecall_daemon_handle_setMode(ecallMode);
+ ECALL_Log("%s: err=%d\n", __FUNCTION__, err);
+ }
+
+ return 0;
+}
+
+static int ecall_daemon_ubus_get_ecallMode(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+ UNUSED(msg);
+
+ char respBuff[16] = {0};
+
+ if (ecall_daemon_get_mode() == 0)
+ {
+ snprintf(respBuff, sizeof(respBuff), "EU");
+ }
+ else if (ecall_daemon_get_mode() == 1)
+ {
+ snprintf(respBuff, sizeof(respBuff), "ERA");;
+ }
+ else
+ {
+ snprintf(respBuff, sizeof(respBuff), "NULL");;
+ }
+
+ ECALL_Log("%s: respBuff=%s\n", __FUNCTION__, respBuff);
+
+ ecall_daemon_mode_string_reply(ctx, req, respBuff);
+
+ return 0;
+}
+
+static int ecall_daemon_ubus_set_smsNum(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+
+ struct blob_attr *tb[ARRAY_SIZE(ecall_daemon_set_smsNum_policy)];
+ struct blob_attr *cur;
+ char *smsNum = NULL;
+ int err = 0;
+
+ err = blobmsg_parse(ecall_daemon_set_smsNum_policy, ARRAY_SIZE(ecall_daemon_set_smsNum_policy), tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ ECALL_Log("%s: blobmsg_parse table fail\n", __FUNCTION__);
+ return -1;
+ }
+
+ cur = tb[0];
+ if (cur)
+ smsNum = blobmsg_get_string(cur);
+ else
+ ECALL_Log("%s: missing parameter1\n", __FUNCTION__);
+
+ ECALL_Log("%s: smsNum=%s\n", __FUNCTION__, smsNum);
+
+ if (smsNum != NULL)
+ {
+ err = ecall_daemon_set_ecallSmsNum(smsNum);
+ ECALL_Log("%s: err=%d\n", __FUNCTION__, err);
+ }
+
+ return 0;
+}
+
+static int ecall_daemon_ubus_get_smsNum(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+ UNUSED(msg);
+
+ char respBuff[64] = {0};
+ char *smsNumber = NULL;
+
+ smsNumber = ecall_daemon_get_ecallSmsNum();
+ if ((smsNumber != NULL) && (strlen(smsNumber) > 0))
+ {
+ snprintf(respBuff, sizeof(respBuff), "%s", smsNumber);
+ }
+
+ ECALL_Log("%s: respBuff=%s\n", __FUNCTION__, respBuff);
+
+ ecall_daemon_smsNum_string_reply(ctx, req, respBuff);
+
+ return 0;
+}
+
+static int ecall_daemon_ubus_send_msdSms(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+
+ struct blob_attr *tb[ARRAY_SIZE(ecall_daemon_send_msdSms_policy)];
+ struct blob_attr *cur;
+ int smsFlag = 0;
+ int err = 0;
+
+ err = blobmsg_parse(ecall_daemon_send_msdSms_policy, ARRAY_SIZE(ecall_daemon_send_msdSms_policy), tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ ECALL_Log("%s: blobmsg_parse table fail\n", __FUNCTION__);
+ return -1;
+ }
+
+ cur = tb[0];
+ if (cur)
+ smsFlag = blobmsg_get_u32(cur);
+ else
+ ECALL_Log("%s: missing parameter1\n", __FUNCTION__);
+
+ ECALL_Log("%s: smsFlag=%d\n", __FUNCTION__, smsFlag);
+
+ err = ecall_daemon_send_msdSms(smsFlag);
+ ECALL_Log("%s: err=%d\n", __FUNCTION__, err);
+
+ return 0;
+}
+
+static int ecall_daemon_ubus_set_ecallTimer(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+
+ struct blob_attr *tb[ARRAY_SIZE(ecall_daemon_set_ecallTimer_policy)];
+ struct blob_attr *cur;
+ char *timerName = NULL;
+ int timerValue = 0;
+ int err = 0;
+
+ err = blobmsg_parse(ecall_daemon_set_ecallTimer_policy, ARRAY_SIZE(ecall_daemon_set_ecallTimer_policy), tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ ECALL_Log("%s: blobmsg_parse table fail\n", __FUNCTION__);
+ return -1;
+ }
+
+ cur = tb[0];
+ if (cur)
+ timerName = blobmsg_get_string(cur);
+ else
+ ECALL_Log("%s: missing parameter1\n", __FUNCTION__);
+
+ cur = tb[1];
+ if (cur)
+ timerValue = blobmsg_get_u32(cur);
+ else
+ ECALL_Log("%s: missing parameter2\n", __FUNCTION__);
+
+ ECALL_Log("%s: timerName=%s, timerValue=%d\n", __FUNCTION__, timerName, timerValue);
+
+ if (timerName != NULL && timerValue >= 0)
+ {
+ err = ecall_daemon_set_ecallTimer(timerName, timerValue);
+ ECALL_Log("%s: err=%d\n", __FUNCTION__, err);
+ }
+
+ return 0;
+}
+
+static int ecall_daemon_ubus_get_ecallTimer(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(obj);
+ UNUSED(method);
+ struct blob_attr *tb[ARRAY_SIZE(ecall_daemon_get_ecallTimer_policy)];
+ struct blob_attr *cur;
+ char *timerName = NULL;
+ int timerValue = 0;
+ int err = 0;
+ char respBuff[256] = {0};
+
+ err = blobmsg_parse(ecall_daemon_get_ecallTimer_policy, ARRAY_SIZE(ecall_daemon_get_ecallTimer_policy), tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ ECALL_Log("%s: blobmsg_parse table fail\n", __FUNCTION__);
+ return -1;
+ }
+
+ cur = tb[0];
+ if (cur)
+ timerName = blobmsg_get_string(cur);
+ else
+ ECALL_Log("%s: missing parameter1\n", __FUNCTION__);
+
+ if (timerName != NULL)
+ {
+ if (0 == strncmp(timerName, "ecallParams", strlen("ecallParams")))
+ {
+ ecall_daemon_get_ecallParams(respBuff, sizeof(respBuff));
+ }
+ else
+ {
+ timerValue = ecall_daemon_get_ecallTimerValue(timerName);
+ memset(respBuff, '\0', sizeof(respBuff));
+ snprintf(respBuff, sizeof(respBuff), "\"%s\"=%d\r\n", timerName, timerValue);
+ }
+ }
+ ECALL_Log("%s: respBuff=%s\n", __FUNCTION__, respBuff);
+
+ ecall_daemon_timerVal_string_reply(ctx, req, respBuff);
+
+ return 0;
+}
+
+static int ecall_daemon_ubus_set_ecallTestNum(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+
+ struct blob_attr *tb[ARRAY_SIZE(ecall_daemon_set_ecallTestNum_policy)];
+ struct blob_attr *cur;
+ char *ecallTestNumber = NULL;
+ char *ecallReconfigNumber = NULL;
+ int err = 0;
+
+ err = blobmsg_parse(ecall_daemon_set_ecallTestNum_policy, ARRAY_SIZE(ecall_daemon_set_ecallTestNum_policy), tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ ECALL_Log("%s: blobmsg_parse table fail\n", __FUNCTION__);
+ return -1;
+ }
+
+ cur = tb[0];
+ if (cur)
+ ecallTestNumber = blobmsg_get_string(cur);
+ else
+ ECALL_Log("%s: missing parameter1\n", __FUNCTION__);
+
+ cur = tb[1];
+ if (cur)
+ ecallReconfigNumber = blobmsg_get_string(cur);
+ else
+ ECALL_Log("%s: missing parameter2\n", __FUNCTION__);
+
+ ECALL_Log("%s: ecallTestNumber=%s, ecallReconfigNumber=%s\n", __FUNCTION__, ecallTestNumber, ecallReconfigNumber);
+
+ err = ecall_daemon_set_ecallTestNum(ecallTestNumber, ecallReconfigNumber);
+
+ ECALL_Log("%s: err=%d\n", __FUNCTION__, err);
+
+ return 0;
+}
+
+static int ecall_daemon_ubus_set_ecallMsd(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+
+ struct blob_attr *tb[ARRAY_SIZE(ecall_daemon_set_ecallMsd_policy)];
+ struct blob_attr *cur;
+ char *ecallMsd = NULL;
+ int err = 0;
+
+ err = blobmsg_parse(ecall_daemon_set_ecallMsd_policy, ARRAY_SIZE(ecall_daemon_set_ecallMsd_policy), tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ ECALL_Log("%s: blobmsg_parse table fail\n", __FUNCTION__);
+ return -1;
+ }
+
+ cur = tb[0];
+ if (cur)
+ ecallMsd = blobmsg_get_string(cur);
+ else
+ ECALL_Log("%s: missing parameter1\n", __FUNCTION__);
+
+ ECALL_Log("%s: ecallMsd=%s\n", __FUNCTION__, ecallMsd);
+
+ if (ecallMsd != NULL)
+ {
+ err = ecall_daemon_set_ecallMsd(ecallMsd);
+ ECALL_Log("%s: err=%d\n", __FUNCTION__, err);
+ }
+
+ return 0;
+}
+
+static int ecall_daemon_ubus_set_ecallPush(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+ UNUSED(msg);
+
+ int err = 0;
+
+ err = ecall_daemon_set_ecallPush(1);
+
+ ECALL_Log("%s: err=%d\n", __FUNCTION__, err);
+
+ return 0;
+}
+
+static const struct ubus_method ecall_methods[] = {
+ UBUS_METHOD("ecall_daemon_ubus_set_ecallMode", ecall_daemon_ubus_set_ecallMode, ecall_daemon_set_mode_policy),
+ UBUS_METHOD_NOARG("ecall_daemon_ubus_get_ecallMode", ecall_daemon_ubus_get_ecallMode),
+ UBUS_METHOD("ecall_daemon_ubus_set_smsNum", ecall_daemon_ubus_set_smsNum, ecall_daemon_set_smsNum_policy),
+ UBUS_METHOD_NOARG("ecall_daemon_ubus_get_smsNum", ecall_daemon_ubus_get_smsNum),
+ UBUS_METHOD("ecall_daemon_ubus_send_msdSms", ecall_daemon_ubus_send_msdSms, ecall_daemon_send_msdSms_policy),
+ UBUS_METHOD("ecall_daemon_ubus_set_ecallTimer", ecall_daemon_ubus_set_ecallTimer, ecall_daemon_set_ecallTimer_policy),
+ UBUS_METHOD("ecall_daemon_ubus_get_ecallTimer", ecall_daemon_ubus_get_ecallTimer, ecall_daemon_get_ecallTimer_policy),
+ UBUS_METHOD("ecall_daemon_ubus_set_ecallTestNum", ecall_daemon_ubus_set_ecallTestNum, ecall_daemon_set_ecallTestNum_policy),
+ UBUS_METHOD("ecall_daemon_ubus_set_ecallMsd", ecall_daemon_ubus_set_ecallMsd, ecall_daemon_set_ecallMsd_policy),
+ UBUS_METHOD_NOARG("ecall_daemon_ubus_set_ecallPush", ecall_daemon_ubus_set_ecallPush),
+};
+
+static struct ubus_object_type ecall_object_type = UBUS_OBJECT_TYPE("ecall_daemon", ecall_methods);
+static struct ubus_object ecall_object = {
+ .name = "ecall_daemon",
+ .type = &ecall_object_type,
+ .methods = ecall_methods,
+ .n_methods = ARRAY_SIZE(ecall_methods),
+};
+
+int main()
+{
+
+ uint32_t id;
+ int ret, retries = 0;
+
+ //set tag name
+ set_service_log_tag("ecall_daemon");
+
+ //ECALL_Log(ecall_daemon_main_0, "ecall_daemon: start\n");s
+ ECALL_Log("ecall_daemon_version: %s\n", ECALL_DAEMON_VERSION);
+
+ uloop_init();
+ while(1)
+ {
+ ecall_ctx = ubus_connect(NULL);
+ if (!ecall_ctx)
+ usleep(200000); //200ms
+ else
+ break;
+ }
+
+ ubus_add_uloop(ecall_ctx);
+
+ ret = ubus_add_object(ecall_ctx, &ecall_object);
+ if (ret) {
+ ECALL_Log("ecall_daemon: Failed to add object: %s\n", ubus_strerror(ret));
+ goto fail1;
+ }
+
+ ret = ubus_register_subscriber(ecall_ctx, &ecall_subscriber);
+ if (ret) {
+ ECALL_Log("ecall_daemon: Failed to add ecall_subscriber: %s\n", ubus_strerror(ret));
+ goto fail2;
+ }
+
+ ecall_subscriber.cb = ecall_subscriber_cb;
+ ecall_subscriber.remove_cb = ecall_subscriber_remove_cb;
+ do {
+ if (RildReady())
+ break;
+ sleep(1);
+ } while (retries++ < 20); //RIL_MAX_RETRIES 20
+
+ if (retries >= 20) {
+ ECALL_Log("ecall_daemon main: Failed to look up RIL object\n");
+ goto fail1;
+ }
+ ECALL_Log("ecall_daemon main: RIL is ready\n");
+
+ //register for PS ind
+ if (ubus_lookup_id(ecall_ctx, "ril.unsol.ps", &id)) {
+ ECALL_Log("ecall_daemon: Failed to look up ril.unsol.ps object\n");
+ goto fail2;
+ }
+
+ ubus_subscribe(ecall_ctx, &ecall_subscriber, id);
+ ECALL_Log("ecall_daemon: subscribe ril.unsol.ps object ok");
+
+ //register for CC ind
+ if (ubus_lookup_id(ecall_ctx, "ril.unsol.cc", &id)) {
+ ECALL_Log("ecall_daemon: Failed to look up ril.unsol.cc object\n");
+ goto fail2;
+ }
+
+ ubus_subscribe(ecall_ctx, &ecall_subscriber, id);
+ ECALL_Log("ecall_daemon: subscribe ril.unsol.cc object ok");
+
+ //register for MM ind
+ if (ubus_lookup_id(ecall_ctx, "ril.unsol.mm", &id)) {
+ ECALL_Log("ecall_daemon: Failed to look up ril.unsol.mm object\n");
+ goto fail2;
+ }
+
+ ubus_subscribe(ecall_ctx, &ecall_subscriber, id);
+ ECALL_Log("ecall_daemon: subscribe ril.unsol.mm object ok");
+
+ //register for msg ind
+ if (ubus_lookup_id(ecall_ctx, "ril.unsol.msg", &id)) {
+ ECALL_Log("ecall_daemon: Failed to look up ril.unsol.msg object\n");
+ goto fail2;
+ }
+
+ ubus_subscribe(ecall_ctx, &ecall_subscriber, id);
+ ECALL_Log("ecall_daemon: subscribe ril.unsol.msg object ok");
+
+ ecall_set_ecall_status(DAEMON_ECALL_IDLE);
+
+ ecall_timer_init();
+
+ ecall_stop_auto_answer();
+
+ uloop_run();
+
+fail2:
+ ubus_remove_object(ecall_ctx, &ecall_object);
+fail1:
+ ubus_free(ecall_ctx);
+ uloop_done();
+ ECALL_Log("ecall_daemon main: exit\n");
+
+ return 0;
+}
+
+#endif