1 /*
2 * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <errno.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <signal.h>
16
17 #ifdef PCBA_3308
18 #include "mic_test_Linux/vibrate_test.h"
19 #include "mic_test_Linux/record_test.h"
20 #endif
21
22 extern int* recordTestWr(int audio_data[], int audio_length);
23 extern int* vibrateTestWr(int audio_data[], int audio_length);
24
25 #define LOG_TAG "echo_ringmic_test"
26 #include "common.h"
27
28 #define AUDIO_CHANNAL_CNT 8
29 #define RINGMIC_BAD_ERROR 93 /* has bad mic */
30
31
32 #define DEBUG_ON 0
33 #if DEBUG_ON
34 #define FLAGS O_WRONLY | O_CREAT | O_TRUNC
35 #define MODE S_IRWXU | S_IXGRP | S_IROTH | S_IXOTH
save_audio_file(char * path,char * buff,int len)36 void save_audio_file(char *path, char *buff, int len)
37 {
38 int fd = 0;
39 int ret = 0;
40 char shell_cmd[200] = {0};
41 sprintf(shell_cmd, "rm -rf %s", path);
42 system(shell_cmd);
43 if ((fd = open(path, FLAGS, MODE)) == -1) {
44 log_err("%s Create %s failed, %s\n", __func__,
45 path, strerror(errno));
46 return;
47 }
48 ret = write(fd, buff, len);
49 if (ret != len) {
50 log_err("%s Write %s failed, %s\n", __func__,
51 path, strerror(errno));
52 return;
53 }
54 log_info("%s file Saved successfully!\n", path);
55 close(fd);
56 return;
57 }
58 #else
59 void save_audio_file(char *paht, char *buff, int len);
60 #endif
61
bytesToInt(char * src,int * length)62 int *bytesToInt(char *src, int *length)
63 {
64 int value = 0, offset = 0, i = 0;
65 int *ret = NULL;
66 int int_len = 0;
67
68 int_len = (*length / 4) + 1;
69 ret = (int *)malloc(int_len * 4);
70 if (!ret)
71 return NULL;
72
73 while ((offset < *length) && (*length - offset >= 4)) {
74 value = (int)((src[offset] & 0xFF) |
75 ((src[offset + 1] & 0xFF) << 8) |
76 ((src[offset + 2] & 0xFF) << 16) |
77 ((src[offset + 3] & 0xFF) << 24));
78 offset += 4;
79 ret[i++] = value;
80 }
81
82 *length = int_len;
83 return ret;
84 }
85
86 #ifdef PCBA_PX3SE
linear_amplification(void * data,void * out,int bytes)87 int linear_amplification(void *data, void *out, int bytes)
88 {
89 int i = 0, j = 0;
90 int mChannels = AUDIO_CHANNAL_CNT;
91 for (i = 0; i < bytes / 4 ; ) {
92 for (j = 0; j < mChannels; j++) {
93 int tmp = 0;
94 int tmp_data = (*((int *)data + i + j));
95 #if 1
96 tmp_data = tmp_data << 2;
97 if(tmp_data > 32767) {
98 tmp_data = 32767;
99 } else if(tmp_data < -32768) {
100 tmp_data = -32768;
101 }
102 #endif
103 tmp = ((((tmp_data & 0xfffff000) >> 12) << 12) | ((j+1) << 8)) & 0xffffff00;
104 *((int *)out + i + j) = tmp;
105 }
106 i += mChannels;
107 }
108 return 0;
109 }
110 #endif
111
112 #ifdef PCBA_3308
linear_amplification(void * data,void * out,int bytes)113 int linear_amplification(void *data, void *out, int bytes)
114 {
115 int i = 0, j = 0;
116 int mChannels = AUDIO_CHANNAL_CNT;
117 for (i = 0; i < bytes / 2; ) {
118 for (j = 0; j < mChannels; j++) {
119 short raw = (*((short *)data + i + j));
120 int tmp_data = (int)raw;
121 #if 1
122 tmp_data = tmp_data << 4;
123 if(tmp_data > 32767) {
124 tmp_data = 32767;
125 } else if(tmp_data < -32768) {
126 tmp_data = -32768;
127 }
128 #endif
129 *((short *)out + i + j) = (short)tmp_data;
130 }
131 i += mChannels;
132 }
133 return 0;
134 }
135 #endif
136
137 #ifdef PCBA_3229GVA
linear_amplification(void * data,void * out,int bytes)138 int linear_amplification(void *data, void *out, int bytes)
139 {
140 int i = 0, j = 0;
141 int mChannels = AUDIO_CHANNAL_CNT;
142 for (i = 0; i < bytes / 2; ) {
143 for (j = 0; j < mChannels; j++) {
144 short raw = (*((short *)data + i + j));
145 int tmp_data = (int)raw;
146 #if 1
147 tmp_data = tmp_data << 7;
148 if(tmp_data > 32767) {
149 tmp_data = 32767;
150 } else if(tmp_data < -32768) {
151 tmp_data = -32768;
152 }
153 #endif
154 *((short *)out + i + j) = (short)tmp_data;
155 }
156 i += mChannels;
157 }
158 return 0;
159 }
160 #endif
161
preProcessBuffer(void * data,void * out,int bytes)162 int preProcessBuffer(void *data, void *out, int bytes)
163 {
164 int i = 0, j = 0;
165
166 for (i = 0; i < bytes / 2 ; ) {
167 for (j = 0; j < AUDIO_CHANNAL_CNT; j++) {
168 int tmp = 0;
169 short tmp_data = (*((short *)data + i + j));
170 tmp = ((tmp_data) << 16 | ((j+1) << 8)) & 0xffffff00;
171 *((int *)out + i + j) = tmp;
172 }
173 i += AUDIO_CHANNAL_CNT;
174 }
175
176 return 0;
177 }
178
add_channel(char * src,char ** dst,int len)179 static int add_channel(char *src, char **dst, int len)
180 {
181 int fd = 0;
182 int dst_len = 0;
183 int ret = 0;
184
185 dst_len = len * 2;
186 *dst = (char *)malloc(dst_len);
187 if (!*dst)
188 return -ENOMEM;
189
190 preProcessBuffer(src, *dst, len);
191
192 return dst_len;
193 }
194 /*
195 * This function includes a ring mic recording test
196 * and vibration test, select the test type by flag.
197 * flag = 0:ring mic record test.
198 * flag = 1:ring mic vibration test.
199 */
ringmic_test(char * result,int flag)200 int ringmic_test(char *result, int flag)
201 {
202 int *record_ret = NULL;
203 int fd = 0;
204 int rf_len = 0; /* record file length */
205 int pre_len = 0;
206 char *rf_buff = NULL; /* record file buffer */
207 char *pre_buff = NULL;
208 char *gain_buff = NULL;
209 int *buffer = NULL;
210 char path[128] = {0};
211 int ret = 0, i = 0;
212
213 /*
214 * According to flag choose to perform "recording test"
215 * or "vibration test". recording at least 10 seconds.
216 */
217 #ifdef PCBA_PX3SE
218 if (flag) {
219 log_info("Start vibration test.\n");
220 sprintf(path, "%s", "/tmp/ringmic_vibration.pcm");
221 /* Play the specified file, and recording. */
222 system("arecord -t raw -f S16_LE -c 8 -r 16000 -d 1 /tmp/ringmic_vibration.pcm");
223 system("rm /tmp/ringmic_vibration.pcm");
224 system("killall -9 arecord");
225 system("aplay /data/vibration.wav &");
226 usleep(200000);
227 system("arecord -t raw -f S16_LE -c 8 -r 16000 /tmp/ringmic_vibration.pcm &");
228 } else {
229 log_info("Start record test.\n");
230 sprintf(path, "%s", "/tmp/ringmic_record.pcm");
231 /* Play the specified file, and recording. */
232 system("arecord -t raw -f S16_LE -c 8 -r 16000 -d 1 /tmp/ringmic_record.pcm");
233 system("rm /tmp/ringmic_record.pcm");
234 system("killall -9 arecord");
235 system("aplay /data/rectest_400hz.wav &");
236 usleep(200000);
237 system("arecord -t raw -f S16_LE -c 8 -r 16000 -d 15 /tmp/ringmic_record.pcm &");
238 }
239 /* recording at least 10 seconds.*/
240 log_info("Recording...\n");
241 sleep(15);
242 #endif
243
244 #ifdef PCBA_3308
245 if (flag) {
246 log_info("Start vibration test.\n");
247 sprintf(path, "%s", "/tmp/ringmic_vibration.pcm");
248 /* Play the specified file, and recording. */
249 system("killall -9 arecord");
250 system("rm /tmp/ringmic_vibration.pcm");
251 system("aplay /data/vibration.wav &");
252 usleep(200000);
253 system("arecord -t raw -f S16_LE -c 8 -r 16000 -d 15 /tmp/ringmic_vibration.pcm");
254 } else {
255 log_info("Start record test.\n");
256 sprintf(path, "%s", "/tmp/ringmic_record.pcm");
257 /* Play the specified file, and recording. */
258 system("killall -9 arecord");
259 system("rm /tmp/ringmic_record.pcm");
260 system("aplay /data/rectest_400hz.wav &");
261 usleep(200000);
262 system("arecord -t raw -f S16_LE -c 8 -r 16000 -d 15 /tmp/ringmic_record.pcm");
263 }
264 #endif
265
266 #ifdef PCBA_3229GVA
267 //TODO:
268 ......
269 #endif
270 system("killall -9 arecord");
271 system("killall aplay");
272
273 log_info("Parsing audio file...\n");
274 fd = open(path, O_RDONLY);
275 if (fd <= 0) {
276 log_err("open %s failed(%s).\n", path, strerror(errno));
277 return errno;
278 }
279 /* get length of the record file. */
280 rf_len = lseek(fd, 0, SEEK_END);
281 rf_buff = (char *)malloc(rf_len);
282 if (!rf_buff) {
283 close(fd);
284 return -ENOMEM;
285 }
286 memset(rf_buff, 0, rf_len);
287 /* Read from the beginning of the file. */
288 lseek(fd, 0, SEEK_SET);
289 ret = read(fd, rf_buff, rf_len);
290 if (ret != rf_len) {
291 log_err("read %s failed(%s).\n", path, strerror(errno));
292 close(fd);
293 free(rf_buff);
294 return errno;
295 }
296 close(fd);
297
298 #ifdef PCBA_PX3SE
299 /* Increase gain */
300 gain_buff = (char *)malloc(rf_len);
301 if (!gain_buff) {
302 close(fd);
303 free(rf_buff);
304 return -ENOMEM;
305 }
306 memset(gain_buff, 0, rf_len);
307 linear_amplification(rf_buff, gain_buff, rf_len);
308 memcpy(rf_buff, gain_buff, rf_len);
309 free(gain_buff);
310 #endif
311 #ifdef PCBA_PX3SE
312 FILE *fp;
313 if (flag)
314 fp = fopen("/tmp/gain-vib.pcm", "wb");
315 else
316 fp = fopen("/tmp/gain-rec.pcm", "wb");
317 if (fp) {
318 fwrite(rf_buff, 1, rf_len, fp);
319 fclose(fp);
320 }
321 #endif
322 #ifdef PCBA_3229GVA
323 //TODO:
324 ......
325 #endif
326
327 /* Add channel numbers to the original recording file */
328 pre_len = add_channel(rf_buff, &pre_buff, rf_len);
329 if (pre_len < 0) {
330 free(rf_buff);
331 return pre_len;
332 }
333 free(rf_buff);
334
335 #ifdef PCBA_3308
336 FILE *fp;
337 if (flag)
338 fp = fopen("/tmp/addchan-vib.pcm", "wb");
339 else
340 fp = fopen("/tmp/addchan-rec.pcm", "wb");
341 if (fp) {
342 fwrite(pre_buff, 1, pre_len, fp);
343 fclose(fp);
344 }
345 #endif
346
347 buffer = bytesToInt(pre_buff, &pre_len);
348 if (!buffer) {
349 log_err("bytesToInt() failed!\n");
350 free(pre_buff);
351 return -ENOMEM;
352 }
353 free(pre_buff);
354
355 #ifdef PCBA_3308
356 if (flag)
357 fp = fopen("/tmp/bytesToInt-vib.pcm", "wb");
358 else
359 fp = fopen("/tmp/bytesToInt-rec.pcm", "wb");
360 if (fp) {
361 fwrite((int *)buffer+16000, 4, pre_len - 32000, fp);
362 fclose(fp);
363 }
364
365 #endif
366 /* Call library interface */
367 if (!flag) {
368 #ifdef PCBA_PX3SE
369 record_ret = recordTestWr((int *)buffer, pre_len - 1280);
370 #endif
371 #ifdef PCBA_3308
372 record_ret = recordTestWr((int *)buffer + 16000, pre_len - 32000);
373 #endif
374 #ifdef PCBA_3229GVA
375 //TODO:
376 record_ret =
377 #endif
378 printf("\n");
379 for (i = 0; i < AUDIO_CHANNAL_CNT; i++) {
380 if (*(record_ret + i)) {
381 log_info("recordTest:#%d mic is bad!\n", i);
382 *result++ = 1;
383 } else {
384 log_info("recordTest:#%d mic is ok!\n", i);
385 *result++ = 0;
386 }
387 }
388
389 system("rm -rf /tmp/ringmic_record.pcm");
390 } else {
391 #ifdef PCBA_PX3SE
392 record_ret = vibrateTestWr((int *)buffer, pre_len - 1280);
393 #endif
394 #ifdef PCBA_3308
395 record_ret = vibrateTestWr((int *)buffer + 16000, pre_len - 32000);
396 #endif
397 #ifdef PCBA_3229GVA
398 //TODO:
399 record_ret =
400 #endif
401 printf("\n");
402 for (i = 0; i < AUDIO_CHANNAL_CNT; i++) {
403 if (*(record_ret + i)) {
404 log_info("vibrationTest:#%d mic is bad!\n", i);
405 *result++ = 1;
406 } else {
407 log_info("vibrationTest:#%d mic is ok!\n", i);
408 *result++ = 0;
409 }
410 }
411
412 system("rm -rf /data/ringmic_vibration.pcm");
413 }
414
415 free(buffer);
416 return 0;
417 }
418
main()419 int main()
420 {
421 char buf[COMMAND_VALUESIZE] = {0};
422 char result[COMMAND_VALUESIZE] = RESULT_PASS;
423 unsigned char record_ret[AUDIO_CHANNAL_CNT] = {0};
424 unsigned char vibration_ret[AUDIO_CHANNAL_CNT] = {0};
425 char *start = NULL;
426 int ispass = 1;
427 int i = 0, ret = 0;
428 #ifdef PCBA_PX3SE
429 system("amixer set Playback 30%");
430 #endif
431 #ifdef PCBA_3308
432 system("amixer set Master Playback 50%");
433 #endif
434 #ifdef PCBA_3229GVA
435 //TODO:
436 ......
437 #endif
438 start = buf;
439 memcpy(start, "vibration:", strlen("vibration:"));
440 start = start + strlen("vibration:");
441 ret = ringmic_test(vibration_ret, 1);
442 if (ret) {
443 memcpy(start, "error", strlen("error"));
444 start += strlen("error");
445 ispass = 0;
446 } else {
447 for (i = 0; i < AUDIO_CHANNAL_CNT; i++) {
448 if (vibration_ret[i]) {
449 ispass = 0;
450 *(start++) = '1' + i;
451 }
452 }
453 }
454 *start++ = ';';
455 sleep(1);
456
457 memcpy(start, "record:", strlen("record:"));
458 start = start + strlen("record:");
459 ret = ringmic_test(record_ret, 0);
460 if (ret) {
461 memcpy(start, "error", strlen("error"));
462 start += strlen("error");
463 strcpy(result, RESULT_FAIL);
464 ispass = 0;
465 } else {
466 for (i = 0; i < AUDIO_CHANNAL_CNT; i++) {
467 if (record_ret[i]) {
468 ispass = 0;
469 *(start++) = '1' + i;
470 }
471 }
472 }
473 *start++ = ';';
474
475 if (!ispass) {
476 strcpy(result, RESULT_FAIL);
477 ret = -RINGMIC_BAD_ERROR;
478 }
479
480 send_msg_to_server(buf, result, ret);
481 return 0;
482 }
483