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