blob: 1858fa1bfc22dc0be17b5333a7ca8ab94ebdb0dc [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;
b.liuc7ffd092024-01-03 15:23:07 +0800325#ifndef MBTK_YX_SUPPORT
liubin281ac462023-07-19 14:22:54 +0800326 if(NULL == mbtk_audio_ubus_db)
327 {
328 printf("mbtk_dtmf_ubus not init!\n");
329 return;
330 }
liubin281ac462023-07-19 14:22:54 +0800331 blob_buf_init(&audio_cm_b, 0);
332 blobmsg_add_u32(&audio_cm_b, "param0", mode);
b.liu1c1c7212023-12-22 16:35:27 +0800333 if ((rc = ubus_invoke(mbtk_audio_ubus_db->ctx,
liubin281ac462023-07-19 14:22:54 +0800334 mbtk_audio_ubus_db->audioif_request_id,
335 AUDIO_UBUS_MODE_SET,
b.liuc7ffd092024-01-03 15:23:07 +0800336 audio_cm_b.head, NULL, NULL, 2 * 1000)) != UBUS_STATUS_OK)
liubin281ac462023-07-19 14:22:54 +0800337 {
liubin281ac462023-07-19 14:22:54 +0800338 printf("%s, ubus_invoke_async %s failed %s\n", __FUNCTION__, AUDIO_UBUS_MODE_SET, ubus_strerror(rc));
339 }
340 else
341 {
342 printf("%s: ubus_invoke_async success\n", __FUNCTION__);
liubin281ac462023-07-19 14:22:54 +0800343 }
b.liuc7ffd092024-01-03 15:23:07 +0800344#else
345 static struct ubus_context *ctx;
346 ctx = ubus_connect(NULL);
347 if (!ctx) {
348 printf("Failed to connect to ubus\n");
349 return;
350 }
351
352 static struct blob_buf b;
353 uint32_t id;
354 int ret;
355 ret = ubus_lookup_id(ctx, AUDIO_UBUS_REQUEST_NAME, &id);
356 if (ret) {
357 printf("ubus_lookup_id() fail.\n");
358 return ret;
359 }
360
361 blob_buf_init(&b, 0);
362 blobmsg_add_u32(&b, "param0", mode);
363 if((ret = ubus_invoke(ctx, id, AUDIO_UBUS_MODE_SET, b.head, NULL, NULL, 0)) != UBUS_STATUS_OK) {
364 printf("ubus_invoke fail:%d.\n", ret);
365 } else {
366 printf("ubus_invoke success.\n");
367 }
368#endif
liubin281ac462023-07-19 14:22:54 +0800369}
LUOJian5bbddc22023-09-04 18:49:11 +0800370
371
372void mbtk_audio_path_enable(int mode)
373{
374 int rc = 0;
b.liuc7ffd092024-01-03 15:23:07 +0800375#ifndef MBTK_YX_SUPPORT
LUOJian5bbddc22023-09-04 18:49:11 +0800376 if(NULL == mbtk_audio_ubus_db)
377 {
378 printf("mbtk_dtmf_ubus not init!\n");
379 return;
380 }
b.liu1c1c7212023-12-22 16:35:27 +0800381
LUOJian5bbddc22023-09-04 18:49:11 +0800382 blob_buf_init(&audio_cm_b, 0);
383 blobmsg_add_u32(&audio_cm_b, "param0", mode);
b.liu1c1c7212023-12-22 16:35:27 +0800384 if ((rc = ubus_invoke(mbtk_audio_ubus_db->ctx,
LUOJian5bbddc22023-09-04 18:49:11 +0800385 mbtk_audio_ubus_db->audioif_request_id,
386 AUDIO_UBUS_PATH_ENABLE,
b.liu1c1c7212023-12-22 16:35:27 +0800387 audio_cm_b.head, NULL, NULL, 0)) != UBUS_STATUS_OK)
LUOJian5bbddc22023-09-04 18:49:11 +0800388 {
LUOJian5bbddc22023-09-04 18:49:11 +0800389 printf("%s, ubus_invoke_async %s failed %s\n", __FUNCTION__, AUDIO_UBUS_PATH_ENABLE, ubus_strerror(rc));
390 }
391 else
392 {
393 printf("%s: ubus_invoke_async success\n", __FUNCTION__);
LUOJian5bbddc22023-09-04 18:49:11 +0800394 }
b.liuc7ffd092024-01-03 15:23:07 +0800395#else
396 static struct ubus_context *ctx;
397 ctx = ubus_connect(NULL);
398 if (!ctx) {
399 printf("Failed to connect to ubus\n");
400 return;
401 }
402
403 static struct blob_buf b;
404 uint32_t id;
405 int ret;
406 ret = ubus_lookup_id(ctx, AUDIO_UBUS_REQUEST_NAME, &id);
407 if (ret) {
408 printf("ubus_lookup_id() fail.\n");
409 return ret;
410 }
411
412 blob_buf_init(&b, 0);
413 blobmsg_add_u32(&b, "param0", mode);
414 if((ret = ubus_invoke(ctx, id, AUDIO_UBUS_PATH_ENABLE, b.head, NULL, NULL, 0)) != UBUS_STATUS_OK) {
415 printf("ubus_invoke fail:%d.\n", ret);
416 } else {
417 printf("ubus_invoke success.\n");
418 }
419
420#endif
LUOJian5bbddc22023-09-04 18:49:11 +0800421}
422
423
424/**
425 * @brief mbtk_audio_switch_pcm
426 *
427 * @details detailed description
428 *
429 * @param param
430 * "param0":UINT32 mode
431 * 0: Turn off MSA PCM
432 * 1: Turn on MSA PCM as NB PCM(i.e. 8KHz sample rate)
433 * 2: Turn on MSA PCM as WB PCM(i.e. 16KHz sample rate)
434 * @return return type
435 */
436void mbtk_audio_switch_pcm(int mode)
437{
438 int rc = 0;
b.liuc7ffd092024-01-03 15:23:07 +0800439#ifndef MBTK_YX_SUPPORT
LUOJian5bbddc22023-09-04 18:49:11 +0800440 if(NULL == mbtk_audio_ubus_db)
441 {
442 printf("mbtk_dtmf_ubus not init!\n");
443 return;
444 }
b.liuc7ffd092024-01-03 15:23:07 +0800445
LUOJian5bbddc22023-09-04 18:49:11 +0800446 blob_buf_init(&audio_cm_b, 0);
447 blobmsg_add_u32(&audio_cm_b, "param0", mode);
b.liuc7ffd092024-01-03 15:23:07 +0800448 if ((rc = ubus_invoke(mbtk_audio_ubus_db->ctx,
LUOJian5bbddc22023-09-04 18:49:11 +0800449 mbtk_audio_ubus_db->audioif_request_id,
450 AUDIO_UBUS_SWITCH_PCM,
b.liuc7ffd092024-01-03 15:23:07 +0800451 audio_cm_b.head, NULL, NULL, 0/*2 * 1000*/)) != UBUS_STATUS_OK)
LUOJian5bbddc22023-09-04 18:49:11 +0800452 {
b.liuc7ffd092024-01-03 15:23:07 +0800453 printf("%s, ubus_invoke %s failed %s\n", __FUNCTION__, AUDIO_UBUS_SWITCH_PCM, ubus_strerror(rc));
LUOJian5bbddc22023-09-04 18:49:11 +0800454 }
455 else
456 {
b.liuc7ffd092024-01-03 15:23:07 +0800457 printf("%s: ubus_invoke success\n", __FUNCTION__);
LUOJian5bbddc22023-09-04 18:49:11 +0800458 }
b.liuc7ffd092024-01-03 15:23:07 +0800459#else
460
461 static struct ubus_context *ctx;
462 ctx = ubus_connect(NULL);
463 if (!ctx) {
464 printf("Failed to connect to ubus\n");
465 return;
466 }
467
468 static struct blob_buf b;
469 uint32_t id;
470 int ret;
471 ret = ubus_lookup_id(ctx, AUDIO_UBUS_REQUEST_NAME, &id);
472 if (ret) {
473 printf("ubus_lookup_id() fail.\n");
474 return ret;
475 }
476
477 blob_buf_init(&b, 0);
478 blobmsg_add_u32(&b, "param0", mode);
479 if((ret = ubus_invoke(ctx, id, AUDIO_UBUS_SWITCH_PCM, b.head, NULL, NULL, 0)) != UBUS_STATUS_OK) {
480 printf("ubus_invoke fail:%d.\n", ret);
481 } else {
482 printf("ubus_invoke success.\n");
483 }
484
485#endif
LUOJian5bbddc22023-09-04 18:49:11 +0800486}
487
liubin281ac462023-07-19 14:22:54 +0800488int mbtk_audio_dsp_set(int type, int gain)
489{
490 LOGE("1type:%d, gain:%d\n", type, gain);
491 int rc = 0;
492 struct ubus_request *req = NULL;
493
494 if(NULL == mbtk_audio_ubus_db)
495 {
496 LOGE("mbtk_dtmf_ubus not init!\n");
497 return -1;
498 }
499 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
500 if (req == NULL)
501 {
502 LOGE("leave %s: lack of memory\n", __FUNCTION__);
503 return -1;
504 }
505
506 memset(req, 0, sizeof(struct ubus_request));
507 blob_buf_init(&audio_cm_b, 0);
508 blobmsg_add_u32(&audio_cm_b, "type", type);
509 blobmsg_add_u32(&audio_cm_b, "gain", gain);
510 if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
511 mbtk_audio_ubus_db->audioif_request_id,
512 AUDIO_UBUS_DSP_SET,
513 audio_cm_b.head, req)) != UBUS_STATUS_OK)
514 {
515 free(req);
516 LOGE("%s, ubus_invoke_async %s failed %s\n", __FUNCTION__, AUDIO_UBUS_DSP_SET, ubus_strerror(rc));
517 return -1;
518 }
519 else
520 {
521 LOGE("%s: ubus_invoke_async success\n", __FUNCTION__);
522 mbtk_audio_ubus_db->work_state++;
523 req->complete_cb = mbtk_ubus_complete_cb;
524 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
525 }
526 return 0;
527}
528/**
529 * @brief mbtk_audio_loopback_start
530 *
531 * @details detailed description
532 *
533 * @param param
534 * device: UINT32
535 * 0: earpiece
536 * 1: speaker
537 * 2: headset
538 * @return return type
539 */
540static void mbtk_audio_loopback_start(int device)
541{
542 int rc = 0;
543 struct ubus_request *req = NULL;
544
545 if(NULL == mbtk_audio_ubus_db)
546 {
547 LOGI("mbtk_dtmf_ubus not init!\n");
548 return;
549 }
550 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
551 if (req == NULL)
552 {
553 LOGI("leave %s: lack of memory\n", __FUNCTION__);
554 return;
555 }
556 memset(req, 0, sizeof(struct ubus_request));
557 blob_buf_init(&audio_cm_b, 0);
558 blobmsg_add_u32(&audio_cm_b, "param0", device);
559 if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
560 mbtk_audio_ubus_db->audioif_request_id,
561 AUDIO_UBUS_LOOPBACK_EN,
562 audio_cm_b.head, req)) != UBUS_STATUS_OK)
563 {
564 free(req);
565 LOGI("%s, ubus_invoke_async volume get failed %s\n", __FUNCTION__, ubus_strerror(rc));
566 }
567 else
568 {
569 LOGI("%s: ubus_invoke_async success\n", __FUNCTION__);
570 req->complete_cb = mbtk_ubus_complete_cb;
571 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
572 }
573}
574
575static void mbtk_audio_loopback_stop(void)
576{
577 int rc = 0;
578
579 if(NULL == mbtk_audio_ubus_db)
580 {
581 printf("mbtk_dtmf_ubus not init!\n");
582 return;
583 }
584 blob_buf_init(&audio_cm_b, 0);
585
586 if ((rc = ubus_invoke(mbtk_audio_ubus_db->ctx,
587 mbtk_audio_ubus_db->audioif_request_id,
588 AUDIO_UBUS_LOOPBACK_DIS,
589 audio_cm_b.head, NULL, 0, 0)) != UBUS_STATUS_OK)
590 {
591 LOGI("%s, ubus_invoke volume get failed %s\n", __FUNCTION__, ubus_strerror(rc));
592 }
593 else
594 {
595 LOGI("%s: ubus_invoke success\n", __FUNCTION__);
596 }
597}
598
599int mbtk_at_loopback(int type)
600{
601 static mbtk_audio_client_handle_type audio_handle = 0;
602 int ret = 0;
603
604 LOGI("%s %d:%d", __FUNCTION__, __LINE__, type);
605 if(0 == type) // Stop
606 {
607 mbtk_audio_loopback_stop();
608 if(audio_handle)
609 {
610 mbtk_audio_ubus_client_deinit(audio_handle);
611 audio_handle = 0;
612 }
613 }
614 else // Start
615 {
616 if(NULL == mbtk_audio_ubus_db)
617 ret = mbtk_audio_ubus_client_init(&audio_handle, NULL);
618 if(ret)
619 {
620 return -1;
621 }
622 mbtk_audio_mode_set(0);
623 mbtk_audio_loopback_start(2);
624 }
625
626 return 0;
627}
628
629/***************************************************** \
630 * Retry mechanism to add subscriber for Audio_if
631\*****************************************************/
632static void mbtk_dtmf_add_subscriber_AudioIf(struct uloop_timeout *timeout)
633{
634 /* add subscriber for Audio_If */
635 if (ubus_lookup_id(mbtk_audio_ubus_db->ctx, DTMFCODE_NOTIFICATION_NAME, &mbtk_audio_ubus_db->audioif_subscriber_id))
636 {
637 printf("%s, Failed to look up %s\n", __FUNCTION__, DTMFCODE_NOTIFICATION_NAME);
638 uloop_timeout_set(timeout, 2000);
639 return;
640 }
641
642 ubus_subscribe(mbtk_audio_ubus_db->ctx, &mbtk_audio_ubus_db->audioif_event, mbtk_audio_ubus_db->audioif_subscriber_id);
643 mbtk_audio_log("Audio_If subscribe %s object ok\n", DTMFCODE_NOTIFICATION_NAME);
644 return;
645}
646/*******************************************************************************\
647* Function: mbtk_dtmf_uBus_pmConstraint
648* Description: Lock/unlock system power management.
649* 0: unlock
650* 1: lock
651* Returns:
652\*******************************************************************************/
653static void mbtk_dtmf_uBus_PMConstraint(int set)
654{
655 FILE *flk;
656 if (mbtk_dtmf_PMConstraintWorks != 0)
657 return; //wake_lock unavailable or not exist. Do nothing
658
659#ifdef PROSLIC_ENABLEFREERUN
660 mbtk_audio_log("%s(%d): %s\n", __FUNCTION__, set, set ? "no sleep" : "sleep after 7s");
661#else
662 mbtk_audio_log("%s(%d): free-run is disabled, no sleep\n", __FUNCTION__, set);
663#endif
664
665 /* Do Not check fopen success. It must be ok, if failed
666 ** (for any reason) better to crash for logging and recovery
667 */
668 flk = fopen("/sys/power/wake_lock", "w");
669 if(set)
670 {
671 fprintf(flk, mbtk_dtmf_UBUS_NAME);
672 }
673 else
674 {
675#ifdef PROSLIC_ENABLEFREERUN
676 /* Clear constraint but with TimeOut enough
677 ** Stay awake for (mbtk_dtmf_DIAL_TIMER + 1) seconds, wait for ringing timer expire
678 */
679 fprintf(flk, mbtk_dtmf_UBUS_NAME " 7000000000"/*nsec*/);
680#endif
681 }
682
683 fclose(flk);
684}
685
686/*******************************************************************************\
687* Function: mbtk_dtmf_uBusInd_AudioIf_remove
688* Description: Handle upon Audio_if remove indication.
689* Returns:
690\*******************************************************************************/
691static void mbtk_dtmf_uBusInd_AudioIf_remove(struct ubus_context *ctx, struct ubus_subscriber *s,
692 uint32_t id)
693{
694 UNUSEDPARAM(ctx);
695 UNUSEDPARAM(s);
696 UNUSEDPARAM(id);
697
698 mbtk_audio_log("%s\n", __FUNCTION__);
699 uloop_timeout_set(&mbtk_dtmf_add_subscribe_timeout_AudioIf, 2000);
700}
701
702
703/*******************************************************************************\
704* Function: mbtk_dtmf_uBusInd_AudioIf
705* Description: Handle upon Audio_If incoming indication.
706* Returns: 0 on success
707\*******************************************************************************/
708static int mbtk_dtmf_uBusInd_AudioIf(struct ubus_context *ctx, struct ubus_object *obj,
709 struct ubus_request_data *req, const char *method,
710 struct blob_attr *msg)
711{
712 UNUSEDPARAM(ctx);
713 UNUSEDPARAM(obj);
714 UNUSEDPARAM(req);
715 UNUSEDPARAM(method);
716
717 char DTMFCode = 0;
718 struct blob_attr *tb[1];
719 int rc = 0;
720
721 //Lock from mbtk_dtmf interrupt handler (mbtk_dtmf_MainLoop)
722 pthread_mutex_lock(&mbtk_dtmf_mutex);
723 mbtk_audio_log("==================================%s : Begin==================================\n", __FUNCTION__);
724 mbtk_dtmf_uBus_PMConstraint(1);
725
726 /*parsing blob to be accessed easily with tb array - parse "1" argument*/
727 rc = blobmsg_parse(dtmf_code_policy, 1, tb, blob_data(msg), blob_len(msg));
728
729 if (rc < 0) {
730 printf("%s: parsing fail, rc = 0x%x\n", __FUNCTION__, rc);
731 }
732 else {
733 DTMFCode = (char)blobmsg_get_u32(tb[0]);
734 if(mbtk_audio_ubus_db->dtmf_cb)
735 mbtk_audio_ubus_db->dtmf_cb(DTMFCode);
736 mbtk_audio_log("%s got DTMF Code: Char[%c]=ASCII[0x%x]\n", __FUNCTION__, DTMFCode, DTMFCode);
737 }
738
739 mbtk_dtmf_uBus_PMConstraint(0);
740 mbtk_audio_log("==================================%s : End==================================", __FUNCTION__);
741 pthread_mutex_unlock(&mbtk_dtmf_mutex);
742
743 return rc;
744}
745
746/*******************************************************************************\
747* Function: mbtk_dtmf_uBusRegisterNotifications
748* Description: Register UBUS notifications of RIL and Audio_If.
749* Returns: 0 on success
750\*******************************************************************************/
751static int mbtk_dtmf_uBusRegisterNotifications(void)
752{
753 int ret = 0;
754
755 /* register UBUS notifications of Audio_If */
756 ret = ubus_register_subscriber(mbtk_audio_ubus_db->ctx, &mbtk_audio_ubus_db->audioif_event);
757 if (ret)
758 {
759 printf("%s Failed to add audio_if watch handler: %s\n", __FUNCTION__, ubus_strerror(ret));
760 return -1;
761 }
762
763 /* specify callback to handle notifications */
764 mbtk_audio_ubus_db->audioif_event.remove_cb = mbtk_dtmf_uBusInd_AudioIf_remove;
765 mbtk_audio_ubus_db->audioif_event.cb = mbtk_dtmf_uBusInd_AudioIf;
766
767 /* add subscribe */
768 uloop_timeout_set(&mbtk_dtmf_add_subscribe_timeout_AudioIf, 0);
769
770 mbtk_audio_log("%s: Make use of DTMF detection in modem.\n", __FUNCTION__);
771
772 return 0;
773}
774
775void mbtk_switch_dtmf_detection_cb(struct ubus_request *req, int rc)
776{
777 if (req)
778 {
779 free(req);
780 req = NULL;
781 }
782 mbtk_audio_log("%s do nothing, rc=%d\n", __FUNCTION__, rc);
783}
784/**
785 * @brief mbtk_switch_dtmf_detection
786 *
787 * @details detailed description
788 *
789 * @param param
790 * “param0": UINT32 onoff
791 * 0: disbale Tx DTMF detection
792 * 1: enable Tx DTMF detection
793 * 2: disbale Rx DTMF detection
794 * 3: enable Rx DTMF detection
795 * @return return type
796 */
797void mbtk_switch_dtmf_detection(unsigned short on_off, unsigned short param1,
798 unsigned short param2, unsigned short param3)
799{
800#if PCM_CTRL_OVER_VCM
801 vcm_DTMFDetection(on_off, param1, param2, param3);
802#else
803 int rc = 0;
804 struct ubus_request *req = NULL;
805
806 if(NULL == mbtk_audio_ubus_db)
807 {
808 printf("mbtk_dtmf_ubus not init!\n");
809 return;
810 }
811 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
812 if (req == NULL)
813 {
814 printf("leave %s: lack of memory\n", __FUNCTION__);
815 return;
816 }
817 memset(req, 0, sizeof(struct ubus_request));
818 blob_buf_init(&audio_cm_b, 0);
819 blobmsg_add_u32(&audio_cm_b, "param0", on_off);
820 blobmsg_add_u32(&audio_cm_b, "param1", param1);
821 blobmsg_add_u32(&audio_cm_b, "param2", param2);
822 blobmsg_add_u32(&audio_cm_b, "param3", param3);
823
824 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)
825 {
826 free(req);
827 printf("%s, ubus_invoke dtmf_detection failed %s\n", __FUNCTION__, ubus_strerror(rc));
828 }
829 else
830 {
831 mbtk_audio_log("%s: ubus_invoke_async success\n", __FUNCTION__);
832 req->complete_cb = mbtk_switch_dtmf_detection_cb;
833 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
834 }
835#endif
836}
837/*******************************************************************************\
838* Function: mbtk_dtmf_uBusInit
839* Description: Init UBUS context and register UBUS notifications of RIL.
840* Returns: 0 on success
841\*******************************************************************************/
842int mbtk_dtmf_uBusInit(void)
843{
844 int rc = 0;
845
846 uloop_init();
847
848 mbtk_audio_ubus_db->ctx = ubus_connect(NULL);
849 if (mbtk_audio_ubus_db->ctx == NULL)
850 {
851 printf(" %s Failed to connect to ubus\n", __FUNCTION__);
852 return -1;
853 }
854
855 ubus_add_uloop(mbtk_audio_ubus_db->ctx);
856
857 /* lookup fail if audio_if is not ready */
858 while(1)
859 {
860 rc = ubus_lookup_id(mbtk_audio_ubus_db->ctx, AUDIO_UBUS_REQUEST_NAME, &mbtk_audio_ubus_db->audioif_request_id);
861 if (0 != rc)
862 {
863 printf("%s, Failed to look up(%s), rc=%d\n", __FUNCTION__, AUDIO_UBUS_REQUEST_NAME, rc);
864 usleep(600000); //600ms
865 }
866 else
867 break;
868 }
869 mbtk_audio_log("%s, ubus_lookup_id(%s) OK\n", __FUNCTION__, AUDIO_UBUS_REQUEST_NAME);
870
871 /* subscribe for RIL & audio_if notifications */
872 if (mbtk_dtmf_uBusRegisterNotifications() != 0)
873 return -1;
874
875 mbtk_audio_log("%s success!\n", __FUNCTION__);
876 return 0;
877}
878
879
880/*******************************************************************************\
881* Function: mbtk_dtmf_uBusRun
882* Description: Start running of UBUS.
883* Returns:
884\*******************************************************************************/
885static void mbtk_audio_ubus_thread(void* hdl)
886{
887 pthread_detach(pthread_self());
888 uloop_run();
889 mbtk_audio_log("%s exit!\n", __FUNCTION__);
890 pthread_exit(NULL);
891}
892
893int mbtk_audio_ubus_client_init(mbtk_audio_client_handle_type *ph_audio, mbtk_dtmf_cb cb)
894{
895 int id;
b.liuc7ffd092024-01-03 15:23:07 +0800896#ifndef MBTK_YX_SUPPORT
liubin281ac462023-07-19 14:22:54 +0800897 // Set call handle.
898 if(ph_audio == NULL || mbtk_audio_ubus_db != NULL)
899 {
900 printf("ARG error or has inited.");
901 return -1;
902 }
903 mbtk_audio_ubus_db = malloc(sizeof(struct mbtk_audio_ubus_db_t));
904 if(NULL == mbtk_audio_ubus_db)
905 {
906 printf("malloc memory error\n");
907 }
908 memset(mbtk_audio_ubus_db, 0, sizeof(struct mbtk_audio_ubus_db_t));
909
910 mbtk_dtmf_PMConstraintWorks = access("/sys/power/wake_lock", R_OK | W_OK);
911 mbtk_dtmf_uBusInit();
912 mbtk_audio_ubus_db->dtmf_cb = cb;
913
914 mbtk_switch_dtmf_detection(3, 50, 4, 3);
915 pthread_create(&mbtk_audio_ubus_db->dtmf_pthread, NULL, (void *)mbtk_audio_ubus_thread, (void *)mbtk_audio_ubus_db);
916
917 *ph_audio = mbtk_audio_ubus_db;
918 LOGI("%s %d:%x", __FUNCTION__, __LINE__, mbtk_audio_ubus_db);
b.liuc7ffd092024-01-03 15:23:07 +0800919#else
920 // Do nothong for YX.
921#endif
liubin281ac462023-07-19 14:22:54 +0800922 return 0;
923}
924
925int mbtk_audio_ubus_client_deinit(mbtk_audio_client_handle_type h_audio)
926{
927 int ret;
b.liuc7ffd092024-01-03 15:23:07 +0800928#ifndef MBTK_YX_SUPPORT
liubin281ac462023-07-19 14:22:54 +0800929 struct mbtk_audio_ubus_db_t *audio_ubus = (struct mbtk_audio_ubus_db_t *)h_audio;
930
931 mbtk_audio_log("%s \n", __FUNCTION__);
932 if(h_audio == NULL || mbtk_audio_ubus_db == NULL)
933 {
934 printf("ARG error or not inited.");
935 return -1;
936 }
937 LOGI("%s %d:%x", __FUNCTION__, __LINE__, audio_ubus);
938 ret = pthread_cancel(audio_ubus->dtmf_pthread);
939 mbtk_audio_log("kill pthread : %d \n", ret);
940 pthread_join(audio_ubus->dtmf_pthread, NULL);
941 do{
942 ret = pthread_kill(audio_ubus->dtmf_pthread, 0);
943 mbtk_audio_log("kill pthread: %d \n", ret);
944 if(ret == ESRCH)
945 mbtk_audio_log("The specified thread does not exist or has terminated\n");
946 else if(ret == EINVAL)
947 mbtk_audio_log("Useless signal\n");
948 else
949 mbtk_audio_log("The thread exists\n");
950 usleep(100000);
951 }while(0 == ret);
952 LOGI("%s %d", __FUNCTION__, __LINE__);
953
954 mbtk_switch_dtmf_detection(2, 0, 0, 0);
955 /*unregister uloop*/
956 /*thread will get here only if uloop stopped*/
957 ubus_free(mbtk_audio_ubus_db->ctx);
958 uloop_done();
959 LOGI("%s %d", __FUNCTION__, __LINE__);
960 free(h_audio);
961 mbtk_audio_ubus_db = NULL;
b.liuc7ffd092024-01-03 15:23:07 +0800962#else
963 // Do nothong for YX.
964#endif
liubin281ac462023-07-19 14:22:54 +0800965 return 0;
966}
967
968/**********************************************************************\
969* Function: APP_Audio_VolumeSet
970* Description: This function is called to send command into audio_if.
971* unsigned int volume(0~100)
972* Returns: 0 on success
973\**********************************************************************/
974void mbtk_audio_ubus_volume_set(unsigned int volume)
975{
976 int rc = 0;
977 struct ubus_request *req = NULL;
978
979 if(NULL == mbtk_audio_ubus_db)
980 {
981 printf("mbtk_dtmf_ubus not init!\n");
982 return;
983 }
984 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
985 if (req == NULL)
986 {
987 printf("leave %s: lack of memory\n", __FUNCTION__);
988 return;
989 }
990 memset(req, 0, sizeof(struct ubus_request));
991 blob_buf_init(&audio_cm_b, 0);
992 blobmsg_add_u32(&audio_cm_b, "param0", volume);
993
994 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)
995 {
996 free(req);
997 printf("%s, ubus_invoke_async volume set failed: %s\n", __FUNCTION__, ubus_strerror(rc));
998 }
999 else
1000 {
1001 mbtk_audio_log("%s: ubus_invoke_async success\n", __FUNCTION__);
1002 req->complete_cb = mbtk_ubus_complete_cb;
1003 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
1004 }
1005}
1006
b.liu79884c22023-09-21 15:10:16 +08001007// TX : 0-10; RX : 11
1008#define MBTK_AUDIO_GAIN_NUM 12
1009void mbtk_audio_ubus_gain_set(uint8 *gain, int gain_num)
1010{
1011 int rc = 0;
1012 struct ubus_request *req = NULL;
1013
1014 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
1015 if (req == NULL)
1016 {
1017 printf("leave %s: lack of memory\n", __FUNCTION__);
1018 return;
1019 }
1020 if(gain_num != MBTK_AUDIO_GAIN_NUM) {
1021 printf("gain_num error.\n");
1022 return;
1023 }
1024 memset(req, 0, sizeof(struct ubus_request));
1025 blob_buf_init(&audio_cm_b, 0);
1026
1027 char name[20];
1028 int i = 0;
1029 // Set TX
1030 for(; i < gain_num - 1; i++) {
1031 memset(name, 0x0, 20);
1032 sprintf(name, "volume_gain_%d", i);
1033 blobmsg_add_u8(&audio_cm_b, name, gain[i]);
1034 }
1035
1036 // Set RX
1037 blobmsg_add_u8(&audio_cm_b, "volume_gain_rx", gain[i]);
1038
1039#if 1
1040 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)
1041 {
1042 free(req);
1043 printf("%s, ubus_invoke_async volume set failed: %s\n", __FUNCTION__, ubus_strerror(rc));
1044 }
1045 else
1046 {
1047 printf("%s: ubus_invoke_async success\n", __FUNCTION__);
1048 req->complete_cb = mbtk_ubus_complete_cb;
1049 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
1050 }
1051#else
1052 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)
1053 {
1054 printf("%s, ubus_invoke_async volume set failed: %s\n", __FUNCTION__, ubus_strerror(rc));
1055 }
1056 else
1057 {
1058 printf("%s: ubus_invoke_async success\n", __FUNCTION__);
1059 }
1060 free(req);
1061#endif
1062}
1063
1064
liubin281ac462023-07-19 14:22:54 +08001065static void audio_volume_get_data_cb (struct ubus_request *req, int type, struct blob_attr *msg)
1066{
1067 UNUSEDPARAM(req);
1068 UNUSEDPARAM(type);
1069 struct blob_attr *tb[1];
1070 unsigned int volume = 888;
1071 int rc = 0;
1072
1073 rc = blobmsg_parse(int_policy, 1, tb, blob_data(msg), blob_len(msg));
1074 if (rc < 0)
1075 {
1076 printf("[%s] parsing blobmsg failed\n", __FUNCTION__);
1077 return;
1078 }
1079
1080 if(tb[0])
1081 volume = blobmsg_get_u32(tb[0]);
1082 if (mbtk_audio_ubus_db->audio_volume_get_cb)
1083 mbtk_audio_ubus_db->audio_volume_get_cb(volume);
1084 mbtk_audio_log("%s; volume:%d\n", __FUNCTION__, volume);
1085}
1086
1087void mbtk_audio_ubus_volume_get(mbtk_volume_cb cb)
1088{
1089 int rc = 0;
1090 struct ubus_request *req = NULL;
1091
1092 if(NULL == mbtk_audio_ubus_db || NULL == cb)
1093 {
1094 printf("mbtk_dtmf_ubus not init or callback invalid!\n");
1095 return;
1096 }
1097 mbtk_audio_ubus_db->audio_volume_get_cb = cb;
1098 req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
1099 if (req == NULL)
1100 {
1101 printf("leave %s: lack of memory\n", __FUNCTION__);
1102 return;
1103 }
1104 memset(req, 0, sizeof(struct ubus_request));
1105 blob_buf_init(&audio_cm_b, 0);
1106
1107 if ((rc = ubus_invoke_async(mbtk_audio_ubus_db->ctx,
1108 mbtk_audio_ubus_db->audioif_request_id,
1109 AUDIO_UBUS_VOLUME_GET,
1110 audio_cm_b.head, req)) != UBUS_STATUS_OK)
1111 {
1112 free(req);
1113 printf("%s, ubus_invoke_async volume get failed %s\n", __FUNCTION__, ubus_strerror(rc));
1114 }
1115 else
1116 {
1117 mbtk_audio_log("%s: ubus_invoke_async success\n", __FUNCTION__);
1118 req->data_cb = audio_volume_get_data_cb;
1119 req->complete_cb = mbtk_ubus_complete_cb;
1120 ubus_complete_request_async(mbtk_audio_ubus_db->ctx, req);
1121 }
1122}