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