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