blob: 5d4af2048d37919cd6ca022cee554feeebc46878 [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001/**
2 * \file mbtk_audio.c
3 * \brief A Documented file.
4 *
5 * Detailed description
6 * \Author: js.wang <js.wang@mobiletek.cn>
7 * \Version: 1.0.0
8 * \Date: 2022-03-31
9 */
10#include <fcntl.h>
11#include <stdint.h>
12#include <limits.h>
13#include <termios.h>
14#include <stdarg.h>
15#include <dirent.h>
16#include <sys/stat.h>
17#include <sys/statfs.h>
18#include <sys/types.h>
19#include "mbtk_log.h"
20#include "mbtk_type.h"
21#include <libubox/blobmsg_json.h>
22#include "libubus.h"
23#include "mbtk_audio.h"
24
25/******************************************************************************\
26 * Macros / Defines
27\******************************************************************************/
28
29#ifndef UNUSEDPARAM
30#define UNUSEDPARAM(a) (void)(a)
31#endif
32
33#define AUDIO_UBUS_REQUEST_NAME "audio_if"
34#define mbtk_dtmf_UBUS_NAME "proslic_uBus" //Used by wake lock
35#define DTMFCODEID "dtmfcode"
36#define DTMFCODE_NOTIFICATION_NAME "audioif.dtmfcode"
37#define AUDIO_UBUS_VOLUME_SET "volume_set"
38#define AUDIO_UBUS_VOLUME_GET "volume_status"
39#define AUDIO_UBUS_MODE_SET "audio_mode_set"
40#define AUDIO_UBUS_DSP_SET "config_dspgain"
41#define AUDIO_UBUS_LOOPBACK_EN "loopback_enable"
42#define AUDIO_UBUS_LOOPBACK_DIS "loopback_disable"
43
44// #define DEBUG 1
45
46#ifdef DEBUG
47 #define mbtk_audio_log(...) mbtk_audio_log(__VA_ARGS__)
48#else
49 #define mbtk_audio_log(...)
50#endif
51
52typedef enum {
53 PARAM_INT_POLICY_0,
54 PARAM_INT_POLICY_1,
55 PARAM_INT_POLICY_2,
56 PARAM_INT_POLICY_3,
57 PARAM_INT_POLICY_MAX,
58} PARAM_INT_POLICY;
59const struct blobmsg_policy int_policy[] ={
60 [PARAM_INT_POLICY_0] = {
61 .name = "param0",
62 .type = BLOBMSG_TYPE_INT32,
63 },
64};
65
66const struct blobmsg_policy dtmf_code_policy[] = {
67 [0] = {
68 .name = DTMFCODEID,
69 .type = BLOBMSG_TYPE_INT32,
70 },
71};
72
73static void mbtk_dtmf_add_subscriber_AudioIf(struct uloop_timeout *timeout);
74static struct uloop_timeout mbtk_dtmf_add_subscribe_timeout_AudioIf =
75{
76 .cb = mbtk_dtmf_add_subscriber_AudioIf,
77};
78
79static struct blob_buf audio_cm_b;
80pthread_mutex_t mbtk_dtmf_mutex;
81int mbtk_dtmf_PMConstraintWorks;
82//For UBUS listening to RILD & audio_if
83struct mbtk_audio_ubus_db_t
84{
85 pthread_t dtmf_pthread;
86 mbtk_dtmf_cb dtmf_cb;
87 mbtk_volume_cb audio_volume_get_cb;
88 int work_state;
89 struct ubus_context *ctx;
90
91 /* Audio_If */
92 struct ubus_subscriber audioif_event;
93 uint32_t audioif_subscriber_id;
94 uint32_t audioif_request_id;
95};
96
97static struct mbtk_audio_ubus_db_t *mbtk_audio_ubus_db = NULL;
98
99
100static int record_fd = 0;
101
102#define AUDIO_FILE_DIR "/data"
103#define MBTK_AUD_DEMO_WAV "/data/demo.wav"
104
105int create_audio_dir(const char *dirname)
106{
107 DIR *p_dir;
108 int res = -1;
109
110 if(NULL == (p_dir = opendir((const char *)dirname)))
111 {
112 if(mkdir(dirname, 0777) == 0)
113 {
114 res = 0;
115 }
116 else
117 {
118 fprintf(stderr, "create audio dir error \n");
119 res = -1;
120 }
121 }
122 else
123 {
124 closedir(p_dir);
125 res = 0;
126 }
127 return res;
128}
129int mbtk_at_play(const char *args)
130{
131 int fd = 0;
132 int play_hdl = 0;
133 char databuf[1024];
134 int size;
135
136 LOGI("%s %d", __FUNCTION__, __LINE__);
137 // play_hdl = Ql_AudPlayer_Open(NULL, NULL);
138 play_hdl = mbtk_audio_open(0, 1, 8000, NULL);
139 if(0 == play_hdl)
140 printf("Ql_AudPlayer_Open fail\n");
141
142 fd = open(MBTK_AUD_DEMO_WAV, O_RDWR);
143 if (fd <= 0)
144 {
145 printf("file open error\n");
146 goto err;
147 }
148 memset(databuf, 0, sizeof(databuf));
149 while(0 < (size = read(fd, databuf, sizeof(databuf))))
150 {
151 if(-1 == mbtk_audio_play_stream(play_hdl, databuf, size))
152 break;
153 }
154 mbtk_audio_log("aplay Stream end \n");
155
156err:
157 if(fd > 0)
158 close(fd);
159 mbtk_audio_close(play_hdl);
160
161 return 0;
162}
163
164void record_cb_func(int cb_result, char* databuf, unsigned int len)
165{
166 int rc;
167
168 if(NULL != databuf && len > 0 && record_fd > 0)
169 {
170 //for debug:save into file
171 rc = write(record_fd, databuf, len);
172 if (rc < 0) {
173 printf("%s: error writing to file!\n", __FUNCTION__);
174 } else if (rc < len) {
175 printf("%s: wrote less the buffer size!\n", __FUNCTION__);
176 }
177 }
178}
179
180int mbtk_at_rec(const char *args)
181{
182 LOGI("%s %d", __FUNCTION__, __LINE__);
183 //hdl = Ql_AudRecorder_Open(NULL, record_cb_func);
184 void *record_hdl = mbtk_audio_open(1, 1, 8000, NULL);
185 if (record_hdl == NULL)
186 {
187 printf("AudRecorder open error\n");
188 return -1;
189 }
190
191 create_audio_dir(AUDIO_FILE_DIR);
192 record_fd = open(MBTK_AUD_DEMO_WAV, O_RDWR|O_CREAT|O_TRUNC, 0644);
193 if (record_fd <= 0)
194 {
195 printf("file open error\n");
196 goto err;
197 }
198
199 if(-1 == mbtk_audio_record(record_hdl, record_cb_func, NULL))
200 {
201 printf("file write error\n");
202 close(record_fd);
203 record_fd = 0;
204 }
205 sleep(10);
206err:
207 mbtk_audio_close(record_hdl);
208 record_hdl = NULL;
209 if(record_fd > 0)
210 {
211 close(record_fd);
212 record_fd = 0;
213 }
214
215 return 0;
216}
217
218static void mbtk_ubus_complete_cb(struct ubus_request *req, int rc)
219{
220 if(NULL == mbtk_audio_ubus_db)
221 {
222 printf("mbtk_dtmf_ubus not init!\n");
223 return;
224 }
225 if (req)
226 {
227 free(req);
228 req = NULL;
229 }
230 mbtk_audio_log("%s do nothing, rc=%d\n", __FUNCTION__, rc);
231 LOGI("%s do nothing, rc=%d\n", __FUNCTION__, rc);
232 if(mbtk_audio_ubus_db->work_state)
233 mbtk_audio_ubus_db->work_state--;
234}
235/**
236 * @brief mbtk_audio_mode_set
237 *
238 * @details detailed description
239 *
240 * @param param
241 * "param0": UINT32
242 * typedef enum {
243 * AUDIO_MODE_INVALID = -2,
244 * AUDIO_MODE_CURRENT = -1,
245 * AUDIO_MODE_NORMAL = 0,
246 * AUDIO_MODE_RINGTONE = 1,
247 * AUDIO_MODE_IN_CALL = 2,
248 * AUDIO_MODE_IN_COMMUNICATION=3,
249 * AUDIO_MODE_IN_VT_CALL= 4,
250 * AUDIO_MODE_CNT,
251 * AUDIO_MODE_MAX = AUDIO_MODE_CNT-1,
252 * } audio_mode_
253 * @return return type
254 */
255static void mbtk_audio_mode_set(int mode)
256{
257 int rc = 0;
258 struct ubus_request *req = NULL;
259
260 if(NULL == mbtk_audio_ubus_db)
261 {
262 printf("mbtk_dtmf_ubus not init!\n");
263 return;
264 }
265 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
266 if (req == NULL)
267 {
268 printf("leave %s: lack of memory\n", __FUNCTION__);
269 return;
270 }
271 memset(req, 0, sizeof(struct ubus_request));
272 blob_buf_init(&audio_cm_b, 0);
273 blobmsg_add_u32(&audio_cm_b, "param0", mode);
274 if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
275 mbtk_audio_ubus_db->audioif_request_id,
276 AUDIO_UBUS_MODE_SET,
277 audio_cm_b.head, req)) != UBUS_STATUS_OK)
278 {
279 free(req);
280 printf("%s, ubus_invoke_async %s failed %s\n", __FUNCTION__, AUDIO_UBUS_MODE_SET, ubus_strerror(rc));
281 }
282 else
283 {
284 printf("%s: ubus_invoke_async success\n", __FUNCTION__);
285 mbtk_audio_ubus_db->work_state++;
286 req->complete_cb = mbtk_ubus_complete_cb;
287 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
288 }
289}
290int mbtk_audio_dsp_set(int type, int gain)
291{
292 LOGE("1type:%d, gain:%d\n", type, gain);
293 int rc = 0;
294 struct ubus_request *req = NULL;
295
296 if(NULL == mbtk_audio_ubus_db)
297 {
298 LOGE("mbtk_dtmf_ubus not init!\n");
299 return -1;
300 }
301 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
302 if (req == NULL)
303 {
304 LOGE("leave %s: lack of memory\n", __FUNCTION__);
305 return -1;
306 }
307
308 memset(req, 0, sizeof(struct ubus_request));
309 blob_buf_init(&audio_cm_b, 0);
310 blobmsg_add_u32(&audio_cm_b, "type", type);
311 blobmsg_add_u32(&audio_cm_b, "gain", gain);
312 if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
313 mbtk_audio_ubus_db->audioif_request_id,
314 AUDIO_UBUS_DSP_SET,
315 audio_cm_b.head, req)) != UBUS_STATUS_OK)
316 {
317 free(req);
318 LOGE("%s, ubus_invoke_async %s failed %s\n", __FUNCTION__, AUDIO_UBUS_DSP_SET, ubus_strerror(rc));
319 return -1;
320 }
321 else
322 {
323 LOGE("%s: ubus_invoke_async success\n", __FUNCTION__);
324 mbtk_audio_ubus_db->work_state++;
325 req->complete_cb = mbtk_ubus_complete_cb;
326 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
327 }
328 return 0;
329}
330/**
331 * @brief mbtk_audio_loopback_start
332 *
333 * @details detailed description
334 *
335 * @param param
336 * device: UINT32
337 * 0: earpiece
338 * 1: speaker
339 * 2: headset
340 * @return return type
341 */
342static void mbtk_audio_loopback_start(int device)
343{
344 int rc = 0;
345 struct ubus_request *req = NULL;
346
347 if(NULL == mbtk_audio_ubus_db)
348 {
349 LOGI("mbtk_dtmf_ubus not init!\n");
350 return;
351 }
352 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
353 if (req == NULL)
354 {
355 LOGI("leave %s: lack of memory\n", __FUNCTION__);
356 return;
357 }
358 memset(req, 0, sizeof(struct ubus_request));
359 blob_buf_init(&audio_cm_b, 0);
360 blobmsg_add_u32(&audio_cm_b, "param0", device);
361 if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
362 mbtk_audio_ubus_db->audioif_request_id,
363 AUDIO_UBUS_LOOPBACK_EN,
364 audio_cm_b.head, req)) != UBUS_STATUS_OK)
365 {
366 free(req);
367 LOGI("%s, ubus_invoke_async volume get failed %s\n", __FUNCTION__, ubus_strerror(rc));
368 }
369 else
370 {
371 LOGI("%s: ubus_invoke_async success\n", __FUNCTION__);
372 req->complete_cb = mbtk_ubus_complete_cb;
373 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
374 }
375}
376
377static void mbtk_audio_loopback_stop(void)
378{
379 int rc = 0;
380
381 if(NULL == mbtk_audio_ubus_db)
382 {
383 printf("mbtk_dtmf_ubus not init!\n");
384 return;
385 }
386 blob_buf_init(&audio_cm_b, 0);
387
388 if ((rc = ubus_invoke(mbtk_audio_ubus_db->ctx,
389 mbtk_audio_ubus_db->audioif_request_id,
390 AUDIO_UBUS_LOOPBACK_DIS,
391 audio_cm_b.head, NULL, 0, 0)) != UBUS_STATUS_OK)
392 {
393 LOGI("%s, ubus_invoke volume get failed %s\n", __FUNCTION__, ubus_strerror(rc));
394 }
395 else
396 {
397 LOGI("%s: ubus_invoke success\n", __FUNCTION__);
398 }
399}
400
401int mbtk_at_loopback(int type)
402{
403 static mbtk_audio_client_handle_type audio_handle = 0;
404 int ret = 0;
405
406 LOGI("%s %d:%d", __FUNCTION__, __LINE__, type);
407 if(0 == type) // Stop
408 {
409 mbtk_audio_loopback_stop();
410 if(audio_handle)
411 {
412 mbtk_audio_ubus_client_deinit(audio_handle);
413 audio_handle = 0;
414 }
415 }
416 else // Start
417 {
418 if(NULL == mbtk_audio_ubus_db)
419 ret = mbtk_audio_ubus_client_init(&audio_handle, NULL);
420 if(ret)
421 {
422 return -1;
423 }
424 mbtk_audio_mode_set(0);
425 mbtk_audio_loopback_start(2);
426 }
427
428 return 0;
429}
430
431/***************************************************** \
432 * Retry mechanism to add subscriber for Audio_if
433\*****************************************************/
434static void mbtk_dtmf_add_subscriber_AudioIf(struct uloop_timeout *timeout)
435{
436 /* add subscriber for Audio_If */
437 if (ubus_lookup_id(mbtk_audio_ubus_db->ctx, DTMFCODE_NOTIFICATION_NAME, &mbtk_audio_ubus_db->audioif_subscriber_id))
438 {
439 printf("%s, Failed to look up %s\n", __FUNCTION__, DTMFCODE_NOTIFICATION_NAME);
440 uloop_timeout_set(timeout, 2000);
441 return;
442 }
443
444 ubus_subscribe(mbtk_audio_ubus_db->ctx, &mbtk_audio_ubus_db->audioif_event, mbtk_audio_ubus_db->audioif_subscriber_id);
445 mbtk_audio_log("Audio_If subscribe %s object ok\n", DTMFCODE_NOTIFICATION_NAME);
446 return;
447}
448/*******************************************************************************\
449* Function: mbtk_dtmf_uBus_pmConstraint
450* Description: Lock/unlock system power management.
451* 0: unlock
452* 1: lock
453* Returns:
454\*******************************************************************************/
455static void mbtk_dtmf_uBus_PMConstraint(int set)
456{
457 FILE *flk;
458 if (mbtk_dtmf_PMConstraintWorks != 0)
459 return; //wake_lock unavailable or not exist. Do nothing
460
461#ifdef PROSLIC_ENABLEFREERUN
462 mbtk_audio_log("%s(%d): %s\n", __FUNCTION__, set, set ? "no sleep" : "sleep after 7s");
463#else
464 mbtk_audio_log("%s(%d): free-run is disabled, no sleep\n", __FUNCTION__, set);
465#endif
466
467 /* Do Not check fopen success. It must be ok, if failed
468 ** (for any reason) better to crash for logging and recovery
469 */
470 flk = fopen("/sys/power/wake_lock", "w");
471 if(set)
472 {
473 fprintf(flk, mbtk_dtmf_UBUS_NAME);
474 }
475 else
476 {
477#ifdef PROSLIC_ENABLEFREERUN
478 /* Clear constraint but with TimeOut enough
479 ** Stay awake for (mbtk_dtmf_DIAL_TIMER + 1) seconds, wait for ringing timer expire
480 */
481 fprintf(flk, mbtk_dtmf_UBUS_NAME " 7000000000"/*nsec*/);
482#endif
483 }
484
485 fclose(flk);
486}
487
488/*******************************************************************************\
489* Function: mbtk_dtmf_uBusInd_AudioIf_remove
490* Description: Handle upon Audio_if remove indication.
491* Returns:
492\*******************************************************************************/
493static void mbtk_dtmf_uBusInd_AudioIf_remove(struct ubus_context *ctx, struct ubus_subscriber *s,
494 uint32_t id)
495{
496 UNUSEDPARAM(ctx);
497 UNUSEDPARAM(s);
498 UNUSEDPARAM(id);
499
500 mbtk_audio_log("%s\n", __FUNCTION__);
501 uloop_timeout_set(&mbtk_dtmf_add_subscribe_timeout_AudioIf, 2000);
502}
503
504
505/*******************************************************************************\
506* Function: mbtk_dtmf_uBusInd_AudioIf
507* Description: Handle upon Audio_If incoming indication.
508* Returns: 0 on success
509\*******************************************************************************/
510static int mbtk_dtmf_uBusInd_AudioIf(struct ubus_context *ctx, struct ubus_object *obj,
511 struct ubus_request_data *req, const char *method,
512 struct blob_attr *msg)
513{
514 UNUSEDPARAM(ctx);
515 UNUSEDPARAM(obj);
516 UNUSEDPARAM(req);
517 UNUSEDPARAM(method);
518
519 char DTMFCode = 0;
520 struct blob_attr *tb[1];
521 int rc = 0;
522
523 //Lock from mbtk_dtmf interrupt handler (mbtk_dtmf_MainLoop)
524 pthread_mutex_lock(&mbtk_dtmf_mutex);
525 mbtk_audio_log("==================================%s : Begin==================================\n", __FUNCTION__);
526 mbtk_dtmf_uBus_PMConstraint(1);
527
528 /*parsing blob to be accessed easily with tb array - parse "1" argument*/
529 rc = blobmsg_parse(dtmf_code_policy, 1, tb, blob_data(msg), blob_len(msg));
530
531 if (rc < 0) {
532 printf("%s: parsing fail, rc = 0x%x\n", __FUNCTION__, rc);
533 }
534 else {
535 DTMFCode = (char)blobmsg_get_u32(tb[0]);
536 if(mbtk_audio_ubus_db->dtmf_cb)
537 mbtk_audio_ubus_db->dtmf_cb(DTMFCode);
538 mbtk_audio_log("%s got DTMF Code: Char[%c]=ASCII[0x%x]\n", __FUNCTION__, DTMFCode, DTMFCode);
539 }
540
541 mbtk_dtmf_uBus_PMConstraint(0);
542 mbtk_audio_log("==================================%s : End==================================", __FUNCTION__);
543 pthread_mutex_unlock(&mbtk_dtmf_mutex);
544
545 return rc;
546}
547
548/*******************************************************************************\
549* Function: mbtk_dtmf_uBusRegisterNotifications
550* Description: Register UBUS notifications of RIL and Audio_If.
551* Returns: 0 on success
552\*******************************************************************************/
553static int mbtk_dtmf_uBusRegisterNotifications(void)
554{
555 int ret = 0;
556
557 /* register UBUS notifications of Audio_If */
558 ret = ubus_register_subscriber(mbtk_audio_ubus_db->ctx, &mbtk_audio_ubus_db->audioif_event);
559 if (ret)
560 {
561 printf("%s Failed to add audio_if watch handler: %s\n", __FUNCTION__, ubus_strerror(ret));
562 return -1;
563 }
564
565 /* specify callback to handle notifications */
566 mbtk_audio_ubus_db->audioif_event.remove_cb = mbtk_dtmf_uBusInd_AudioIf_remove;
567 mbtk_audio_ubus_db->audioif_event.cb = mbtk_dtmf_uBusInd_AudioIf;
568
569 /* add subscribe */
570 uloop_timeout_set(&mbtk_dtmf_add_subscribe_timeout_AudioIf, 0);
571
572 mbtk_audio_log("%s: Make use of DTMF detection in modem.\n", __FUNCTION__);
573
574 return 0;
575}
576
577void mbtk_switch_dtmf_detection_cb(struct ubus_request *req, int rc)
578{
579 if (req)
580 {
581 free(req);
582 req = NULL;
583 }
584 mbtk_audio_log("%s do nothing, rc=%d\n", __FUNCTION__, rc);
585}
586/**
587 * @brief mbtk_switch_dtmf_detection
588 *
589 * @details detailed description
590 *
591 * @param param
592 * “param0": UINT32 onoff
593 * 0: disbale Tx DTMF detection
594 * 1: enable Tx DTMF detection
595 * 2: disbale Rx DTMF detection
596 * 3: enable Rx DTMF detection
597 * @return return type
598 */
599void mbtk_switch_dtmf_detection(unsigned short on_off, unsigned short param1,
600 unsigned short param2, unsigned short param3)
601{
602#if PCM_CTRL_OVER_VCM
603 vcm_DTMFDetection(on_off, param1, param2, param3);
604#else
605 int rc = 0;
606 struct ubus_request *req = NULL;
607
608 if(NULL == mbtk_audio_ubus_db)
609 {
610 printf("mbtk_dtmf_ubus not init!\n");
611 return;
612 }
613 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
614 if (req == NULL)
615 {
616 printf("leave %s: lack of memory\n", __FUNCTION__);
617 return;
618 }
619 memset(req, 0, sizeof(struct ubus_request));
620 blob_buf_init(&audio_cm_b, 0);
621 blobmsg_add_u32(&audio_cm_b, "param0", on_off);
622 blobmsg_add_u32(&audio_cm_b, "param1", param1);
623 blobmsg_add_u32(&audio_cm_b, "param2", param2);
624 blobmsg_add_u32(&audio_cm_b, "param3", param3);
625
626 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)
627 {
628 free(req);
629 printf("%s, ubus_invoke dtmf_detection failed %s\n", __FUNCTION__, ubus_strerror(rc));
630 }
631 else
632 {
633 mbtk_audio_log("%s: ubus_invoke_async success\n", __FUNCTION__);
634 req->complete_cb = mbtk_switch_dtmf_detection_cb;
635 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
636 }
637#endif
638}
639/*******************************************************************************\
640* Function: mbtk_dtmf_uBusInit
641* Description: Init UBUS context and register UBUS notifications of RIL.
642* Returns: 0 on success
643\*******************************************************************************/
644int mbtk_dtmf_uBusInit(void)
645{
646 int rc = 0;
647
648 uloop_init();
649
650 mbtk_audio_ubus_db->ctx = ubus_connect(NULL);
651 if (mbtk_audio_ubus_db->ctx == NULL)
652 {
653 printf(" %s Failed to connect to ubus\n", __FUNCTION__);
654 return -1;
655 }
656
657 ubus_add_uloop(mbtk_audio_ubus_db->ctx);
658
659 /* lookup fail if audio_if is not ready */
660 while(1)
661 {
662 rc = ubus_lookup_id(mbtk_audio_ubus_db->ctx, AUDIO_UBUS_REQUEST_NAME, &mbtk_audio_ubus_db->audioif_request_id);
663 if (0 != rc)
664 {
665 printf("%s, Failed to look up(%s), rc=%d\n", __FUNCTION__, AUDIO_UBUS_REQUEST_NAME, rc);
666 usleep(600000); //600ms
667 }
668 else
669 break;
670 }
671 mbtk_audio_log("%s, ubus_lookup_id(%s) OK\n", __FUNCTION__, AUDIO_UBUS_REQUEST_NAME);
672
673 /* subscribe for RIL & audio_if notifications */
674 if (mbtk_dtmf_uBusRegisterNotifications() != 0)
675 return -1;
676
677 mbtk_audio_log("%s success!\n", __FUNCTION__);
678 return 0;
679}
680
681
682/*******************************************************************************\
683* Function: mbtk_dtmf_uBusRun
684* Description: Start running of UBUS.
685* Returns:
686\*******************************************************************************/
687static void mbtk_audio_ubus_thread(void* hdl)
688{
689 pthread_detach(pthread_self());
690 uloop_run();
691 mbtk_audio_log("%s exit!\n", __FUNCTION__);
692 pthread_exit(NULL);
693}
694
695int mbtk_audio_ubus_client_init(mbtk_audio_client_handle_type *ph_audio, mbtk_dtmf_cb cb)
696{
697 int id;
698
699 // Set call handle.
700 if(ph_audio == NULL || mbtk_audio_ubus_db != NULL)
701 {
702 printf("ARG error or has inited.");
703 return -1;
704 }
705 mbtk_audio_ubus_db = malloc(sizeof(struct mbtk_audio_ubus_db_t));
706 if(NULL == mbtk_audio_ubus_db)
707 {
708 printf("malloc memory error\n");
709 }
710 memset(mbtk_audio_ubus_db, 0, sizeof(struct mbtk_audio_ubus_db_t));
711
712 mbtk_dtmf_PMConstraintWorks = access("/sys/power/wake_lock", R_OK | W_OK);
713 mbtk_dtmf_uBusInit();
714 mbtk_audio_ubus_db->dtmf_cb = cb;
715
716 mbtk_switch_dtmf_detection(3, 50, 4, 3);
717 pthread_create(&mbtk_audio_ubus_db->dtmf_pthread, NULL, (void *)mbtk_audio_ubus_thread, (void *)mbtk_audio_ubus_db);
718
719 *ph_audio = mbtk_audio_ubus_db;
720 LOGI("%s %d:%x", __FUNCTION__, __LINE__, mbtk_audio_ubus_db);
721
722 return 0;
723}
724
725int mbtk_audio_ubus_client_deinit(mbtk_audio_client_handle_type h_audio)
726{
727 int ret;
728 struct mbtk_audio_ubus_db_t *audio_ubus = (struct mbtk_audio_ubus_db_t *)h_audio;
729
730 mbtk_audio_log("%s \n", __FUNCTION__);
731 if(h_audio == NULL || mbtk_audio_ubus_db == NULL)
732 {
733 printf("ARG error or not inited.");
734 return -1;
735 }
736 LOGI("%s %d:%x", __FUNCTION__, __LINE__, audio_ubus);
737 ret = pthread_cancel(audio_ubus->dtmf_pthread);
738 mbtk_audio_log("kill pthread : %d \n", ret);
739 pthread_join(audio_ubus->dtmf_pthread, NULL);
740 do{
741 ret = pthread_kill(audio_ubus->dtmf_pthread, 0);
742 mbtk_audio_log("kill pthread: %d \n", ret);
743 if(ret == ESRCH)
744 mbtk_audio_log("The specified thread does not exist or has terminated\n");
745 else if(ret == EINVAL)
746 mbtk_audio_log("Useless signal\n");
747 else
748 mbtk_audio_log("The thread exists\n");
749 usleep(100000);
750 }while(0 == ret);
751 LOGI("%s %d", __FUNCTION__, __LINE__);
752
753 mbtk_switch_dtmf_detection(2, 0, 0, 0);
754 /*unregister uloop*/
755 /*thread will get here only if uloop stopped*/
756 ubus_free(mbtk_audio_ubus_db->ctx);
757 uloop_done();
758 LOGI("%s %d", __FUNCTION__, __LINE__);
759 free(h_audio);
760 mbtk_audio_ubus_db = NULL;
761
762 return 0;
763}
764
765/**********************************************************************\
766* Function: APP_Audio_VolumeSet
767* Description: This function is called to send command into audio_if.
768* unsigned int volume(0~100)
769* Returns: 0 on success
770\**********************************************************************/
771void mbtk_audio_ubus_volume_set(unsigned int volume)
772{
773 int rc = 0;
774 struct ubus_request *req = NULL;
775
776 if(NULL == mbtk_audio_ubus_db)
777 {
778 printf("mbtk_dtmf_ubus not init!\n");
779 return;
780 }
781 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
782 if (req == NULL)
783 {
784 printf("leave %s: lack of memory\n", __FUNCTION__);
785 return;
786 }
787 memset(req, 0, sizeof(struct ubus_request));
788 blob_buf_init(&audio_cm_b, 0);
789 blobmsg_add_u32(&audio_cm_b, "param0", volume);
790
791 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)
792 {
793 free(req);
794 printf("%s, ubus_invoke_async volume set failed: %s\n", __FUNCTION__, ubus_strerror(rc));
795 }
796 else
797 {
798 mbtk_audio_log("%s: ubus_invoke_async success\n", __FUNCTION__);
799 req->complete_cb = mbtk_ubus_complete_cb;
800 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
801 }
802}
803
804static void audio_volume_get_data_cb (struct ubus_request *req, int type, struct blob_attr *msg)
805{
806 UNUSEDPARAM(req);
807 UNUSEDPARAM(type);
808 struct blob_attr *tb[1];
809 unsigned int volume = 888;
810 int rc = 0;
811
812 rc = blobmsg_parse(int_policy, 1, tb, blob_data(msg), blob_len(msg));
813 if (rc < 0)
814 {
815 printf("[%s] parsing blobmsg failed\n", __FUNCTION__);
816 return;
817 }
818
819 if(tb[0])
820 volume = blobmsg_get_u32(tb[0]);
821 if (mbtk_audio_ubus_db->audio_volume_get_cb)
822 mbtk_audio_ubus_db->audio_volume_get_cb(volume);
823 mbtk_audio_log("%s; volume:%d\n", __FUNCTION__, volume);
824}
825
826void mbtk_audio_ubus_volume_get(mbtk_volume_cb cb)
827{
828 int rc = 0;
829 struct ubus_request *req = NULL;
830
831 if(NULL == mbtk_audio_ubus_db || NULL == cb)
832 {
833 printf("mbtk_dtmf_ubus not init or callback invalid!\n");
834 return;
835 }
836 mbtk_audio_ubus_db->audio_volume_get_cb = cb;
837 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
838 if (req == NULL)
839 {
840 printf("leave %s: lack of memory\n", __FUNCTION__);
841 return;
842 }
843 memset(req, 0, sizeof(struct ubus_request));
844 blob_buf_init(&audio_cm_b, 0);
845
846 if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
847 mbtk_audio_ubus_db->audioif_request_id,
848 AUDIO_UBUS_VOLUME_GET,
849 audio_cm_b.head, req)) != UBUS_STATUS_OK)
850 {
851 free(req);
852 printf("%s, ubus_invoke_async volume get failed %s\n", __FUNCTION__, ubus_strerror(rc));
853 }
854 else
855 {
856 mbtk_audio_log("%s: ubus_invoke_async success\n", __FUNCTION__);
857 req->data_cb = audio_volume_get_data_cb;
858 req->complete_cb = mbtk_ubus_complete_cb;
859 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
860 }
861}