Add toolchain and mbtk source
Change-Id: Ie12546301367ea59240bf23d5e184ad7e36e40b3
diff --git a/mbtk/mbtk_lib/src/mbtk_audio.c b/mbtk/mbtk_lib/src/mbtk_audio.c
new file mode 100755
index 0000000..5d4af20
--- /dev/null
+++ b/mbtk/mbtk_lib/src/mbtk_audio.c
@@ -0,0 +1,861 @@
+/**
+ * \file mbtk_audio.c
+ * \brief A Documented file.
+ *
+ * Detailed description
+ * \Author: js.wang <js.wang@mobiletek.cn>
+ * \Version: 1.0.0
+ * \Date: 2022-03-31
+ */
+#include <fcntl.h>
+#include <stdint.h>
+#include <limits.h>
+#include <termios.h>
+#include <stdarg.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/types.h>
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+#include <libubox/blobmsg_json.h>
+#include "libubus.h"
+#include "mbtk_audio.h"
+
+/******************************************************************************\
+ * Macros / Defines
+\******************************************************************************/
+
+#ifndef UNUSEDPARAM
+#define UNUSEDPARAM(a) (void)(a)
+#endif
+
+#define AUDIO_UBUS_REQUEST_NAME "audio_if"
+#define mbtk_dtmf_UBUS_NAME "proslic_uBus" //Used by wake lock
+#define DTMFCODEID "dtmfcode"
+#define DTMFCODE_NOTIFICATION_NAME "audioif.dtmfcode"
+#define AUDIO_UBUS_VOLUME_SET "volume_set"
+#define AUDIO_UBUS_VOLUME_GET "volume_status"
+#define AUDIO_UBUS_MODE_SET "audio_mode_set"
+#define AUDIO_UBUS_DSP_SET "config_dspgain"
+#define AUDIO_UBUS_LOOPBACK_EN "loopback_enable"
+#define AUDIO_UBUS_LOOPBACK_DIS "loopback_disable"
+
+// #define DEBUG 1
+
+#ifdef DEBUG
+ #define mbtk_audio_log(...) mbtk_audio_log(__VA_ARGS__)
+#else
+ #define mbtk_audio_log(...)
+#endif
+
+typedef enum {
+ PARAM_INT_POLICY_0,
+ PARAM_INT_POLICY_1,
+ PARAM_INT_POLICY_2,
+ PARAM_INT_POLICY_3,
+ PARAM_INT_POLICY_MAX,
+} PARAM_INT_POLICY;
+const struct blobmsg_policy int_policy[] ={
+ [PARAM_INT_POLICY_0] = {
+ .name = "param0",
+ .type = BLOBMSG_TYPE_INT32,
+ },
+};
+
+const struct blobmsg_policy dtmf_code_policy[] = {
+ [0] = {
+ .name = DTMFCODEID,
+ .type = BLOBMSG_TYPE_INT32,
+ },
+};
+
+static void mbtk_dtmf_add_subscriber_AudioIf(struct uloop_timeout *timeout);
+static struct uloop_timeout mbtk_dtmf_add_subscribe_timeout_AudioIf =
+{
+ .cb = mbtk_dtmf_add_subscriber_AudioIf,
+};
+
+static struct blob_buf audio_cm_b;
+pthread_mutex_t mbtk_dtmf_mutex;
+int mbtk_dtmf_PMConstraintWorks;
+//For UBUS listening to RILD & audio_if
+struct mbtk_audio_ubus_db_t
+{
+ pthread_t dtmf_pthread;
+ mbtk_dtmf_cb dtmf_cb;
+ mbtk_volume_cb audio_volume_get_cb;
+ int work_state;
+ struct ubus_context *ctx;
+
+ /* Audio_If */
+ struct ubus_subscriber audioif_event;
+ uint32_t audioif_subscriber_id;
+ uint32_t audioif_request_id;
+};
+
+static struct mbtk_audio_ubus_db_t *mbtk_audio_ubus_db = NULL;
+
+
+static int record_fd = 0;
+
+#define AUDIO_FILE_DIR "/data"
+#define MBTK_AUD_DEMO_WAV "/data/demo.wav"
+
+int create_audio_dir(const char *dirname)
+{
+ DIR *p_dir;
+ int res = -1;
+
+ if(NULL == (p_dir = opendir((const char *)dirname)))
+ {
+ if(mkdir(dirname, 0777) == 0)
+ {
+ res = 0;
+ }
+ else
+ {
+ fprintf(stderr, "create audio dir error \n");
+ res = -1;
+ }
+ }
+ else
+ {
+ closedir(p_dir);
+ res = 0;
+ }
+ return res;
+}
+int mbtk_at_play(const char *args)
+{
+ int fd = 0;
+ int play_hdl = 0;
+ char databuf[1024];
+ int size;
+
+ LOGI("%s %d", __FUNCTION__, __LINE__);
+ // play_hdl = Ql_AudPlayer_Open(NULL, NULL);
+ play_hdl = mbtk_audio_open(0, 1, 8000, NULL);
+ if(0 == play_hdl)
+ printf("Ql_AudPlayer_Open fail\n");
+
+ fd = open(MBTK_AUD_DEMO_WAV, O_RDWR);
+ if (fd <= 0)
+ {
+ printf("file open error\n");
+ goto err;
+ }
+ memset(databuf, 0, sizeof(databuf));
+ while(0 < (size = read(fd, databuf, sizeof(databuf))))
+ {
+ if(-1 == mbtk_audio_play_stream(play_hdl, databuf, size))
+ break;
+ }
+ mbtk_audio_log("aplay Stream end \n");
+
+err:
+ if(fd > 0)
+ close(fd);
+ mbtk_audio_close(play_hdl);
+
+ return 0;
+}
+
+void record_cb_func(int cb_result, char* databuf, unsigned int len)
+{
+ int rc;
+
+ if(NULL != databuf && len > 0 && record_fd > 0)
+ {
+ //for debug:save into file
+ rc = write(record_fd, databuf, len);
+ if (rc < 0) {
+ printf("%s: error writing to file!\n", __FUNCTION__);
+ } else if (rc < len) {
+ printf("%s: wrote less the buffer size!\n", __FUNCTION__);
+ }
+ }
+}
+
+int mbtk_at_rec(const char *args)
+{
+ LOGI("%s %d", __FUNCTION__, __LINE__);
+ //hdl = Ql_AudRecorder_Open(NULL, record_cb_func);
+ void *record_hdl = mbtk_audio_open(1, 1, 8000, NULL);
+ if (record_hdl == NULL)
+ {
+ printf("AudRecorder open error\n");
+ return -1;
+ }
+
+ create_audio_dir(AUDIO_FILE_DIR);
+ record_fd = open(MBTK_AUD_DEMO_WAV, O_RDWR|O_CREAT|O_TRUNC, 0644);
+ if (record_fd <= 0)
+ {
+ printf("file open error\n");
+ goto err;
+ }
+
+ if(-1 == mbtk_audio_record(record_hdl, record_cb_func, NULL))
+ {
+ printf("file write error\n");
+ close(record_fd);
+ record_fd = 0;
+ }
+ sleep(10);
+err:
+ mbtk_audio_close(record_hdl);
+ record_hdl = NULL;
+ if(record_fd > 0)
+ {
+ close(record_fd);
+ record_fd = 0;
+ }
+
+ return 0;
+}
+
+static void mbtk_ubus_complete_cb(struct ubus_request *req, int rc)
+{
+ if(NULL == mbtk_audio_ubus_db)
+ {
+ printf("mbtk_dtmf_ubus not init!\n");
+ return;
+ }
+ if (req)
+ {
+ free(req);
+ req = NULL;
+ }
+ mbtk_audio_log("%s do nothing, rc=%d\n", __FUNCTION__, rc);
+ LOGI("%s do nothing, rc=%d\n", __FUNCTION__, rc);
+ if(mbtk_audio_ubus_db->work_state)
+ mbtk_audio_ubus_db->work_state--;
+}
+/**
+ * @brief mbtk_audio_mode_set
+ *
+ * @details detailed description
+ *
+ * @param param
+ * "param0": UINT32
+ * typedef enum {
+ * AUDIO_MODE_INVALID = -2,
+ * AUDIO_MODE_CURRENT = -1,
+ * AUDIO_MODE_NORMAL = 0,
+ * AUDIO_MODE_RINGTONE = 1,
+ * AUDIO_MODE_IN_CALL = 2,
+ * AUDIO_MODE_IN_COMMUNICATION=3,
+ * AUDIO_MODE_IN_VT_CALL= 4,
+ * AUDIO_MODE_CNT,
+ * AUDIO_MODE_MAX = AUDIO_MODE_CNT-1,
+ * } audio_mode_
+ * @return return type
+ */
+static void mbtk_audio_mode_set(int mode)
+{
+ int rc = 0;
+ struct ubus_request *req = NULL;
+
+ if(NULL == mbtk_audio_ubus_db)
+ {
+ printf("mbtk_dtmf_ubus not init!\n");
+ return;
+ }
+ req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
+ if (req == NULL)
+ {
+ printf("leave %s: lack of memory\n", __FUNCTION__);
+ return;
+ }
+ memset(req, 0, sizeof(struct ubus_request));
+ blob_buf_init(&audio_cm_b, 0);
+ blobmsg_add_u32(&audio_cm_b, "param0", mode);
+ if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
+ mbtk_audio_ubus_db->audioif_request_id,
+ AUDIO_UBUS_MODE_SET,
+ audio_cm_b.head, req)) != UBUS_STATUS_OK)
+ {
+ free(req);
+ printf("%s, ubus_invoke_async %s failed %s\n", __FUNCTION__, AUDIO_UBUS_MODE_SET, ubus_strerror(rc));
+ }
+ else
+ {
+ printf("%s: ubus_invoke_async success\n", __FUNCTION__);
+ mbtk_audio_ubus_db->work_state++;
+ req->complete_cb = mbtk_ubus_complete_cb;
+ ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
+ }
+}
+int mbtk_audio_dsp_set(int type, int gain)
+{
+ LOGE("1type:%d, gain:%d\n", type, gain);
+ int rc = 0;
+ struct ubus_request *req = NULL;
+
+ if(NULL == mbtk_audio_ubus_db)
+ {
+ LOGE("mbtk_dtmf_ubus not init!\n");
+ return -1;
+ }
+ req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
+ if (req == NULL)
+ {
+ LOGE("leave %s: lack of memory\n", __FUNCTION__);
+ return -1;
+ }
+
+ memset(req, 0, sizeof(struct ubus_request));
+ blob_buf_init(&audio_cm_b, 0);
+ blobmsg_add_u32(&audio_cm_b, "type", type);
+ blobmsg_add_u32(&audio_cm_b, "gain", gain);
+ if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
+ mbtk_audio_ubus_db->audioif_request_id,
+ AUDIO_UBUS_DSP_SET,
+ audio_cm_b.head, req)) != UBUS_STATUS_OK)
+ {
+ free(req);
+ LOGE("%s, ubus_invoke_async %s failed %s\n", __FUNCTION__, AUDIO_UBUS_DSP_SET, ubus_strerror(rc));
+ return -1;
+ }
+ else
+ {
+ LOGE("%s: ubus_invoke_async success\n", __FUNCTION__);
+ mbtk_audio_ubus_db->work_state++;
+ req->complete_cb = mbtk_ubus_complete_cb;
+ ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
+ }
+ return 0;
+}
+/**
+ * @brief mbtk_audio_loopback_start
+ *
+ * @details detailed description
+ *
+ * @param param
+ * device: UINT32
+ * 0: earpiece
+ * 1: speaker
+ * 2: headset
+ * @return return type
+ */
+static void mbtk_audio_loopback_start(int device)
+{
+ int rc = 0;
+ struct ubus_request *req = NULL;
+
+ if(NULL == mbtk_audio_ubus_db)
+ {
+ LOGI("mbtk_dtmf_ubus not init!\n");
+ return;
+ }
+ req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
+ if (req == NULL)
+ {
+ LOGI("leave %s: lack of memory\n", __FUNCTION__);
+ return;
+ }
+ memset(req, 0, sizeof(struct ubus_request));
+ blob_buf_init(&audio_cm_b, 0);
+ blobmsg_add_u32(&audio_cm_b, "param0", device);
+ if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
+ mbtk_audio_ubus_db->audioif_request_id,
+ AUDIO_UBUS_LOOPBACK_EN,
+ audio_cm_b.head, req)) != UBUS_STATUS_OK)
+ {
+ free(req);
+ LOGI("%s, ubus_invoke_async volume get failed %s\n", __FUNCTION__, ubus_strerror(rc));
+ }
+ else
+ {
+ LOGI("%s: ubus_invoke_async success\n", __FUNCTION__);
+ req->complete_cb = mbtk_ubus_complete_cb;
+ ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
+ }
+}
+
+static void mbtk_audio_loopback_stop(void)
+{
+ int rc = 0;
+
+ if(NULL == mbtk_audio_ubus_db)
+ {
+ printf("mbtk_dtmf_ubus not init!\n");
+ return;
+ }
+ blob_buf_init(&audio_cm_b, 0);
+
+ if ((rc = ubus_invoke(mbtk_audio_ubus_db->ctx,
+ mbtk_audio_ubus_db->audioif_request_id,
+ AUDIO_UBUS_LOOPBACK_DIS,
+ audio_cm_b.head, NULL, 0, 0)) != UBUS_STATUS_OK)
+ {
+ LOGI("%s, ubus_invoke volume get failed %s\n", __FUNCTION__, ubus_strerror(rc));
+ }
+ else
+ {
+ LOGI("%s: ubus_invoke success\n", __FUNCTION__);
+ }
+}
+
+int mbtk_at_loopback(int type)
+{
+ static mbtk_audio_client_handle_type audio_handle = 0;
+ int ret = 0;
+
+ LOGI("%s %d:%d", __FUNCTION__, __LINE__, type);
+ if(0 == type) // Stop
+ {
+ mbtk_audio_loopback_stop();
+ if(audio_handle)
+ {
+ mbtk_audio_ubus_client_deinit(audio_handle);
+ audio_handle = 0;
+ }
+ }
+ else // Start
+ {
+ if(NULL == mbtk_audio_ubus_db)
+ ret = mbtk_audio_ubus_client_init(&audio_handle, NULL);
+ if(ret)
+ {
+ return -1;
+ }
+ mbtk_audio_mode_set(0);
+ mbtk_audio_loopback_start(2);
+ }
+
+ return 0;
+}
+
+/***************************************************** \
+ * Retry mechanism to add subscriber for Audio_if
+\*****************************************************/
+static void mbtk_dtmf_add_subscriber_AudioIf(struct uloop_timeout *timeout)
+{
+ /* add subscriber for Audio_If */
+ if (ubus_lookup_id(mbtk_audio_ubus_db->ctx, DTMFCODE_NOTIFICATION_NAME, &mbtk_audio_ubus_db->audioif_subscriber_id))
+ {
+ printf("%s, Failed to look up %s\n", __FUNCTION__, DTMFCODE_NOTIFICATION_NAME);
+ uloop_timeout_set(timeout, 2000);
+ return;
+ }
+
+ ubus_subscribe(mbtk_audio_ubus_db->ctx, &mbtk_audio_ubus_db->audioif_event, mbtk_audio_ubus_db->audioif_subscriber_id);
+ mbtk_audio_log("Audio_If subscribe %s object ok\n", DTMFCODE_NOTIFICATION_NAME);
+ return;
+}
+/*******************************************************************************\
+* Function: mbtk_dtmf_uBus_pmConstraint
+* Description: Lock/unlock system power management.
+* 0: unlock
+* 1: lock
+* Returns:
+\*******************************************************************************/
+static void mbtk_dtmf_uBus_PMConstraint(int set)
+{
+ FILE *flk;
+ if (mbtk_dtmf_PMConstraintWorks != 0)
+ return; //wake_lock unavailable or not exist. Do nothing
+
+#ifdef PROSLIC_ENABLEFREERUN
+ mbtk_audio_log("%s(%d): %s\n", __FUNCTION__, set, set ? "no sleep" : "sleep after 7s");
+#else
+ mbtk_audio_log("%s(%d): free-run is disabled, no sleep\n", __FUNCTION__, set);
+#endif
+
+ /* Do Not check fopen success. It must be ok, if failed
+ ** (for any reason) better to crash for logging and recovery
+ */
+ flk = fopen("/sys/power/wake_lock", "w");
+ if(set)
+ {
+ fprintf(flk, mbtk_dtmf_UBUS_NAME);
+ }
+ else
+ {
+#ifdef PROSLIC_ENABLEFREERUN
+ /* Clear constraint but with TimeOut enough
+ ** Stay awake for (mbtk_dtmf_DIAL_TIMER + 1) seconds, wait for ringing timer expire
+ */
+ fprintf(flk, mbtk_dtmf_UBUS_NAME " 7000000000"/*nsec*/);
+#endif
+ }
+
+ fclose(flk);
+}
+
+/*******************************************************************************\
+* Function: mbtk_dtmf_uBusInd_AudioIf_remove
+* Description: Handle upon Audio_if remove indication.
+* Returns:
+\*******************************************************************************/
+static void mbtk_dtmf_uBusInd_AudioIf_remove(struct ubus_context *ctx, struct ubus_subscriber *s,
+ uint32_t id)
+{
+ UNUSEDPARAM(ctx);
+ UNUSEDPARAM(s);
+ UNUSEDPARAM(id);
+
+ mbtk_audio_log("%s\n", __FUNCTION__);
+ uloop_timeout_set(&mbtk_dtmf_add_subscribe_timeout_AudioIf, 2000);
+}
+
+
+/*******************************************************************************\
+* Function: mbtk_dtmf_uBusInd_AudioIf
+* Description: Handle upon Audio_If incoming indication.
+* Returns: 0 on success
+\*******************************************************************************/
+static int mbtk_dtmf_uBusInd_AudioIf(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSEDPARAM(ctx);
+ UNUSEDPARAM(obj);
+ UNUSEDPARAM(req);
+ UNUSEDPARAM(method);
+
+ char DTMFCode = 0;
+ struct blob_attr *tb[1];
+ int rc = 0;
+
+ //Lock from mbtk_dtmf interrupt handler (mbtk_dtmf_MainLoop)
+ pthread_mutex_lock(&mbtk_dtmf_mutex);
+ mbtk_audio_log("==================================%s : Begin==================================\n", __FUNCTION__);
+ mbtk_dtmf_uBus_PMConstraint(1);
+
+ /*parsing blob to be accessed easily with tb array - parse "1" argument*/
+ rc = blobmsg_parse(dtmf_code_policy, 1, tb, blob_data(msg), blob_len(msg));
+
+ if (rc < 0) {
+ printf("%s: parsing fail, rc = 0x%x\n", __FUNCTION__, rc);
+ }
+ else {
+ DTMFCode = (char)blobmsg_get_u32(tb[0]);
+ if(mbtk_audio_ubus_db->dtmf_cb)
+ mbtk_audio_ubus_db->dtmf_cb(DTMFCode);
+ mbtk_audio_log("%s got DTMF Code: Char[%c]=ASCII[0x%x]\n", __FUNCTION__, DTMFCode, DTMFCode);
+ }
+
+ mbtk_dtmf_uBus_PMConstraint(0);
+ mbtk_audio_log("==================================%s : End==================================", __FUNCTION__);
+ pthread_mutex_unlock(&mbtk_dtmf_mutex);
+
+ return rc;
+}
+
+/*******************************************************************************\
+* Function: mbtk_dtmf_uBusRegisterNotifications
+* Description: Register UBUS notifications of RIL and Audio_If.
+* Returns: 0 on success
+\*******************************************************************************/
+static int mbtk_dtmf_uBusRegisterNotifications(void)
+{
+ int ret = 0;
+
+ /* register UBUS notifications of Audio_If */
+ ret = ubus_register_subscriber(mbtk_audio_ubus_db->ctx, &mbtk_audio_ubus_db->audioif_event);
+ if (ret)
+ {
+ printf("%s Failed to add audio_if watch handler: %s\n", __FUNCTION__, ubus_strerror(ret));
+ return -1;
+ }
+
+ /* specify callback to handle notifications */
+ mbtk_audio_ubus_db->audioif_event.remove_cb = mbtk_dtmf_uBusInd_AudioIf_remove;
+ mbtk_audio_ubus_db->audioif_event.cb = mbtk_dtmf_uBusInd_AudioIf;
+
+ /* add subscribe */
+ uloop_timeout_set(&mbtk_dtmf_add_subscribe_timeout_AudioIf, 0);
+
+ mbtk_audio_log("%s: Make use of DTMF detection in modem.\n", __FUNCTION__);
+
+ return 0;
+}
+
+void mbtk_switch_dtmf_detection_cb(struct ubus_request *req, int rc)
+{
+ if (req)
+ {
+ free(req);
+ req = NULL;
+ }
+ mbtk_audio_log("%s do nothing, rc=%d\n", __FUNCTION__, rc);
+}
+/**
+ * @brief mbtk_switch_dtmf_detection
+ *
+ * @details detailed description
+ *
+ * @param param
+ * “param0": UINT32 onoff
+ * 0: disbale Tx DTMF detection
+ * 1: enable Tx DTMF detection
+ * 2: disbale Rx DTMF detection
+ * 3: enable Rx DTMF detection
+ * @return return type
+ */
+void mbtk_switch_dtmf_detection(unsigned short on_off, unsigned short param1,
+ unsigned short param2, unsigned short param3)
+{
+#if PCM_CTRL_OVER_VCM
+ vcm_DTMFDetection(on_off, param1, param2, param3);
+#else
+ int rc = 0;
+ struct ubus_request *req = NULL;
+
+ if(NULL == mbtk_audio_ubus_db)
+ {
+ printf("mbtk_dtmf_ubus not init!\n");
+ return;
+ }
+ req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
+ if (req == NULL)
+ {
+ printf("leave %s: lack of memory\n", __FUNCTION__);
+ return;
+ }
+ memset(req, 0, sizeof(struct ubus_request));
+ blob_buf_init(&audio_cm_b, 0);
+ blobmsg_add_u32(&audio_cm_b, "param0", on_off);
+ blobmsg_add_u32(&audio_cm_b, "param1", param1);
+ blobmsg_add_u32(&audio_cm_b, "param2", param2);
+ blobmsg_add_u32(&audio_cm_b, "param3", param3);
+
+ if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx, mbtk_audio_ubus_db->audioif_request_id, "dtmf_detection", audio_cm_b.head, req)) != UBUS_STATUS_OK)
+ {
+ free(req);
+ printf("%s, ubus_invoke dtmf_detection failed %s\n", __FUNCTION__, ubus_strerror(rc));
+ }
+ else
+ {
+ mbtk_audio_log("%s: ubus_invoke_async success\n", __FUNCTION__);
+ req->complete_cb = mbtk_switch_dtmf_detection_cb;
+ ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
+ }
+#endif
+}
+/*******************************************************************************\
+* Function: mbtk_dtmf_uBusInit
+* Description: Init UBUS context and register UBUS notifications of RIL.
+* Returns: 0 on success
+\*******************************************************************************/
+int mbtk_dtmf_uBusInit(void)
+{
+ int rc = 0;
+
+ uloop_init();
+
+ mbtk_audio_ubus_db->ctx = ubus_connect(NULL);
+ if (mbtk_audio_ubus_db->ctx == NULL)
+ {
+ printf(" %s Failed to connect to ubus\n", __FUNCTION__);
+ return -1;
+ }
+
+ ubus_add_uloop(mbtk_audio_ubus_db->ctx);
+
+ /* lookup fail if audio_if is not ready */
+ while(1)
+ {
+ rc = ubus_lookup_id(mbtk_audio_ubus_db->ctx, AUDIO_UBUS_REQUEST_NAME, &mbtk_audio_ubus_db->audioif_request_id);
+ if (0 != rc)
+ {
+ printf("%s, Failed to look up(%s), rc=%d\n", __FUNCTION__, AUDIO_UBUS_REQUEST_NAME, rc);
+ usleep(600000); //600ms
+ }
+ else
+ break;
+ }
+ mbtk_audio_log("%s, ubus_lookup_id(%s) OK\n", __FUNCTION__, AUDIO_UBUS_REQUEST_NAME);
+
+ /* subscribe for RIL & audio_if notifications */
+ if (mbtk_dtmf_uBusRegisterNotifications() != 0)
+ return -1;
+
+ mbtk_audio_log("%s success!\n", __FUNCTION__);
+ return 0;
+}
+
+
+/*******************************************************************************\
+* Function: mbtk_dtmf_uBusRun
+* Description: Start running of UBUS.
+* Returns:
+\*******************************************************************************/
+static void mbtk_audio_ubus_thread(void* hdl)
+{
+ pthread_detach(pthread_self());
+ uloop_run();
+ mbtk_audio_log("%s exit!\n", __FUNCTION__);
+ pthread_exit(NULL);
+}
+
+int mbtk_audio_ubus_client_init(mbtk_audio_client_handle_type *ph_audio, mbtk_dtmf_cb cb)
+{
+ int id;
+
+ // Set call handle.
+ if(ph_audio == NULL || mbtk_audio_ubus_db != NULL)
+ {
+ printf("ARG error or has inited.");
+ return -1;
+ }
+ mbtk_audio_ubus_db = malloc(sizeof(struct mbtk_audio_ubus_db_t));
+ if(NULL == mbtk_audio_ubus_db)
+ {
+ printf("malloc memory error\n");
+ }
+ memset(mbtk_audio_ubus_db, 0, sizeof(struct mbtk_audio_ubus_db_t));
+
+ mbtk_dtmf_PMConstraintWorks = access("/sys/power/wake_lock", R_OK | W_OK);
+ mbtk_dtmf_uBusInit();
+ mbtk_audio_ubus_db->dtmf_cb = cb;
+
+ mbtk_switch_dtmf_detection(3, 50, 4, 3);
+ pthread_create(&mbtk_audio_ubus_db->dtmf_pthread, NULL, (void *)mbtk_audio_ubus_thread, (void *)mbtk_audio_ubus_db);
+
+ *ph_audio = mbtk_audio_ubus_db;
+ LOGI("%s %d:%x", __FUNCTION__, __LINE__, mbtk_audio_ubus_db);
+
+ return 0;
+}
+
+int mbtk_audio_ubus_client_deinit(mbtk_audio_client_handle_type h_audio)
+{
+ int ret;
+ struct mbtk_audio_ubus_db_t *audio_ubus = (struct mbtk_audio_ubus_db_t *)h_audio;
+
+ mbtk_audio_log("%s \n", __FUNCTION__);
+ if(h_audio == NULL || mbtk_audio_ubus_db == NULL)
+ {
+ printf("ARG error or not inited.");
+ return -1;
+ }
+ LOGI("%s %d:%x", __FUNCTION__, __LINE__, audio_ubus);
+ ret = pthread_cancel(audio_ubus->dtmf_pthread);
+ mbtk_audio_log("kill pthread : %d \n", ret);
+ pthread_join(audio_ubus->dtmf_pthread, NULL);
+ do{
+ ret = pthread_kill(audio_ubus->dtmf_pthread, 0);
+ mbtk_audio_log("kill pthread: %d \n", ret);
+ if(ret == ESRCH)
+ mbtk_audio_log("The specified thread does not exist or has terminated\n");
+ else if(ret == EINVAL)
+ mbtk_audio_log("Useless signal\n");
+ else
+ mbtk_audio_log("The thread exists\n");
+ usleep(100000);
+ }while(0 == ret);
+ LOGI("%s %d", __FUNCTION__, __LINE__);
+
+ mbtk_switch_dtmf_detection(2, 0, 0, 0);
+ /*unregister uloop*/
+ /*thread will get here only if uloop stopped*/
+ ubus_free(mbtk_audio_ubus_db->ctx);
+ uloop_done();
+ LOGI("%s %d", __FUNCTION__, __LINE__);
+ free(h_audio);
+ mbtk_audio_ubus_db = NULL;
+
+ return 0;
+}
+
+/**********************************************************************\
+* Function: APP_Audio_VolumeSet
+* Description: This function is called to send command into audio_if.
+* unsigned int volume(0~100)
+* Returns: 0 on success
+\**********************************************************************/
+void mbtk_audio_ubus_volume_set(unsigned int volume)
+{
+ int rc = 0;
+ struct ubus_request *req = NULL;
+
+ if(NULL == mbtk_audio_ubus_db)
+ {
+ printf("mbtk_dtmf_ubus not init!\n");
+ return;
+ }
+ req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
+ if (req == NULL)
+ {
+ printf("leave %s: lack of memory\n", __FUNCTION__);
+ return;
+ }
+ memset(req, 0, sizeof(struct ubus_request));
+ blob_buf_init(&audio_cm_b, 0);
+ blobmsg_add_u32(&audio_cm_b, "param0", volume);
+
+ if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx, mbtk_audio_ubus_db->audioif_request_id, AUDIO_UBUS_VOLUME_SET, audio_cm_b.head, req)) != UBUS_STATUS_OK)
+ {
+ free(req);
+ printf("%s, ubus_invoke_async volume set failed: %s\n", __FUNCTION__, ubus_strerror(rc));
+ }
+ else
+ {
+ mbtk_audio_log("%s: ubus_invoke_async success\n", __FUNCTION__);
+ req->complete_cb = mbtk_ubus_complete_cb;
+ ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
+ }
+}
+
+static void audio_volume_get_data_cb (struct ubus_request *req, int type, struct blob_attr *msg)
+{
+ UNUSEDPARAM(req);
+ UNUSEDPARAM(type);
+ struct blob_attr *tb[1];
+ unsigned int volume = 888;
+ int rc = 0;
+
+ rc = blobmsg_parse(int_policy, 1, tb, blob_data(msg), blob_len(msg));
+ if (rc < 0)
+ {
+ printf("[%s] parsing blobmsg failed\n", __FUNCTION__);
+ return;
+ }
+
+ if(tb[0])
+ volume = blobmsg_get_u32(tb[0]);
+ if (mbtk_audio_ubus_db->audio_volume_get_cb)
+ mbtk_audio_ubus_db->audio_volume_get_cb(volume);
+ mbtk_audio_log("%s; volume:%d\n", __FUNCTION__, volume);
+}
+
+void mbtk_audio_ubus_volume_get(mbtk_volume_cb cb)
+{
+ int rc = 0;
+ struct ubus_request *req = NULL;
+
+ if(NULL == mbtk_audio_ubus_db || NULL == cb)
+ {
+ printf("mbtk_dtmf_ubus not init or callback invalid!\n");
+ return;
+ }
+ mbtk_audio_ubus_db->audio_volume_get_cb = cb;
+ req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
+ if (req == NULL)
+ {
+ printf("leave %s: lack of memory\n", __FUNCTION__);
+ return;
+ }
+ memset(req, 0, sizeof(struct ubus_request));
+ blob_buf_init(&audio_cm_b, 0);
+
+ if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
+ mbtk_audio_ubus_db->audioif_request_id,
+ AUDIO_UBUS_VOLUME_GET,
+ audio_cm_b.head, req)) != UBUS_STATUS_OK)
+ {
+ free(req);
+ printf("%s, ubus_invoke_async volume get failed %s\n", __FUNCTION__, ubus_strerror(rc));
+ }
+ else
+ {
+ mbtk_audio_log("%s: ubus_invoke_async success\n", __FUNCTION__);
+ req->data_cb = audio_volume_get_data_cb;
+ req->complete_cb = mbtk_ubus_complete_cb;
+ ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
+ }
+}