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