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