apps/testing/drivertest:add audio drivertest
Signed-off-by: jinxiuxu <jinxiuxu@xiaomi.com>
This commit is contained in:
parent
7dcb0c79c3
commit
4f7abe0231
@ -94,4 +94,9 @@ MAINSRC += drivertest_uart.c
|
||||
PROGNAME += cmocka_driver_uart
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_AUDIO),)
|
||||
MAINSRC += drivertest_audio.c
|
||||
PROGNAME += cmocka_driver_audio
|
||||
endif
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
|
794
testing/drivertest/drivertest_audio.c
Normal file
794
testing/drivertest/drivertest_audio.c
Normal file
@ -0,0 +1,794 @@
|
||||
/****************************************************************************
|
||||
* apps/testing/drivertest/drivertest_audio.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <cmocka.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <mqueue.h>
|
||||
#include <debug.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <nuttx/audio/audio.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define OPTARG_TO_VALUE(value, type, base) \
|
||||
do \
|
||||
{ \
|
||||
FAR char *ptr; \
|
||||
value = (type)strtoul(optarg, &ptr, base); \
|
||||
if (*ptr != '\0') \
|
||||
{ \
|
||||
printf("Parameter error: %s\n", optarg); \
|
||||
audio_test_help(argv[0], EXIT_FAILURE); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct audio_state_s
|
||||
{
|
||||
char outfile[PATH_MAX];
|
||||
char outdev[PATH_MAX];
|
||||
char indev[PATH_MAX];
|
||||
int outdev_fd;
|
||||
int indev_fd;
|
||||
int out_fd;
|
||||
|
||||
uint32_t samprate;
|
||||
uint32_t format;
|
||||
uint32_t bpsamp;
|
||||
uint32_t chans;
|
||||
uint32_t chmap;
|
||||
|
||||
char mqname[16];
|
||||
int direction;
|
||||
uint32_t duration;
|
||||
uint32_t idx;
|
||||
mqd_t mq;
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
FAR void *session;
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: audio_test_writebuffer
|
||||
****************************************************************************/
|
||||
|
||||
static int audio_test_writebuffer(FAR struct audio_state_s *state,
|
||||
FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (state->out_fd == -1)
|
||||
{
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
ret = write(state->out_fd, apb->samp, apb->nbytes);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
apb->curbyte = 0;
|
||||
apb->flags = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: player_readbuffer
|
||||
****************************************************************************/
|
||||
|
||||
static int audio_test_readbuffer(FAR struct audio_state_s *state,
|
||||
FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
if (state->out_fd == -1)
|
||||
{
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
apb->nbytes = read(state->out_fd, apb->samp, apb->nmaxbytes);
|
||||
apb->curbyte = 0;
|
||||
apb->flags = 0;
|
||||
|
||||
if (apb->nbytes < apb->nmaxbytes)
|
||||
{
|
||||
close(state->out_fd);
|
||||
state->out_fd = -1;
|
||||
apb->flags |= AUDIO_APB_FINAL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: audio_test_enqueuebuffer
|
||||
****************************************************************************/
|
||||
|
||||
static int audio_test_enqueuebuffer(FAR struct audio_state_s *state,
|
||||
FAR struct ap_buffer_s *apb,
|
||||
int direction)
|
||||
{
|
||||
struct audio_buf_desc_s bufdesc;
|
||||
int ret = 0;
|
||||
int fd;
|
||||
|
||||
fd = direction == AUDIO_TYPE_OUTPUT ?
|
||||
state->outdev_fd :
|
||||
state->indev_fd;
|
||||
|
||||
apb->nbytes = apb->nmaxbytes;
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
bufdesc.session = state->session;
|
||||
#endif
|
||||
|
||||
bufdesc.numbytes = apb->nbytes;
|
||||
bufdesc.u.buffer = apb;
|
||||
|
||||
ret = ioctl(fd, AUDIOIOC_ENQUEUEBUFFER, (unsigned long)&bufdesc);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int audio_test_alloc_buffer(FAR struct audio_state_s *state,
|
||||
FAR struct ap_buffer_s **bufs,
|
||||
FAR struct ap_buffer_info_s *buf_info,
|
||||
int direction)
|
||||
{
|
||||
struct audio_buf_desc_s buf_desc;
|
||||
int ret = 0;
|
||||
int fd;
|
||||
int x;
|
||||
|
||||
fd = direction == AUDIO_TYPE_OUTPUT ?
|
||||
state->outdev_fd :
|
||||
state->indev_fd;
|
||||
|
||||
for (x = 0; x < buf_info->nbuffers; x++)
|
||||
{
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
buf_desc.session = state->session;
|
||||
#endif
|
||||
buf_desc.numbytes = buf_info->buffer_size;
|
||||
buf_desc.u.pbuffer = &bufs[x];
|
||||
|
||||
ret = ioctl(fd, AUDIOIOC_ALLOCBUFFER, (unsigned long)&buf_desc);
|
||||
if (ret != sizeof(buf_desc))
|
||||
{
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
err_out:
|
||||
free(bufs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int audio_test_free_buffer(FAR struct audio_state_s *state,
|
||||
FAR struct ap_buffer_s **bufs,
|
||||
FAR struct ap_buffer_info_s *buf_info,
|
||||
int direction)
|
||||
{
|
||||
struct audio_buf_desc_s buf_desc;
|
||||
int ret = 0;
|
||||
int fd;
|
||||
int x;
|
||||
|
||||
fd = direction == AUDIO_TYPE_OUTPUT ?
|
||||
state->outdev_fd :
|
||||
state->indev_fd;
|
||||
|
||||
for (x = 0; x < buf_info->nbuffers; x++)
|
||||
{
|
||||
if (bufs[x] != NULL)
|
||||
{
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
buf_desc.session = state->session;
|
||||
#endif
|
||||
buf_desc.u.buffer = bufs[x];
|
||||
ret = ioctl(fd, AUDIOIOC_FREEBUFFER, (unsigned long)&buf_desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void audio_test_help(FAR const char *progname, int exitcode)
|
||||
{
|
||||
printf("Usage: %s\n"
|
||||
" -a <test case>\n"
|
||||
" -t <duration>\n"
|
||||
" -i <input device e.g./dev/audio/pcm0c>\n"
|
||||
" -o <output device e.g./dev/audio/pcm0p>\n"
|
||||
" -p <output file>\n"
|
||||
" -f <format>\n"
|
||||
" -b <bytes per sample> \n"
|
||||
" -s <sample rate> \n"
|
||||
" -c <channles> \n",
|
||||
progname);
|
||||
printf(" [-a testcase] selects the testcase\n"
|
||||
" Case 1: Capture\n"
|
||||
" Case 2: Playack\n"
|
||||
" Case 3: First Capture, and then Playback\n"
|
||||
);
|
||||
printf(" -h shows this message and exits\n");
|
||||
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: parse_commandline
|
||||
****************************************************************************/
|
||||
|
||||
static void parse_commandline(FAR struct audio_state_s *state, int argc,
|
||||
FAR char **argv)
|
||||
{
|
||||
int option;
|
||||
|
||||
while ((option = getopt(argc, argv, "a:t::o::i::f::p:c::b::s::")) != ERROR)
|
||||
{
|
||||
switch (option)
|
||||
{
|
||||
case 'a':
|
||||
{
|
||||
OPTARG_TO_VALUE(state->direction, uint32_t, 10);
|
||||
break;
|
||||
}
|
||||
|
||||
case 't':
|
||||
{
|
||||
OPTARG_TO_VALUE(state->duration, uint32_t, 10);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
{
|
||||
strcpy(state->outdev, optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'i':
|
||||
{
|
||||
strcpy(state->indev, optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
{
|
||||
if (!strcmp(optarg, "mp3"))
|
||||
{
|
||||
state->format = AUDIO_FMT_MP3;
|
||||
}
|
||||
else
|
||||
{
|
||||
state->format = AUDIO_FMT_PCM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
{
|
||||
strcpy(state->outfile, optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
{
|
||||
OPTARG_TO_VALUE(state->chans, uint32_t, 10);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'b':
|
||||
{
|
||||
OPTARG_TO_VALUE(state->bpsamp, uint32_t, 10);
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
OPTARG_TO_VALUE(state->samprate, uint32_t, 10);
|
||||
break;
|
||||
}
|
||||
|
||||
case '?':
|
||||
printf("Unknown option: %c\n", optopt);
|
||||
audio_test_help(argv[0], EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: audio_test_prepare
|
||||
****************************************************************************/
|
||||
|
||||
static int audio_test_prepare(FAR struct audio_state_s *state,
|
||||
FAR struct ap_buffer_info_s *buf_info,
|
||||
int direction)
|
||||
{
|
||||
struct audio_caps_desc_s cap_desc;
|
||||
struct audio_caps_s caps;
|
||||
int ret = 0;
|
||||
int fd;
|
||||
|
||||
fd = direction == AUDIO_TYPE_OUTPUT ?
|
||||
state->outdev_fd :
|
||||
state->indev_fd;
|
||||
|
||||
if (direction == AUDIO_TYPE_OUTPUT)
|
||||
{
|
||||
state->out_fd = open(state->outfile, O_RDONLY);
|
||||
}
|
||||
else
|
||||
{
|
||||
state->out_fd = open(state->outfile, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
}
|
||||
|
||||
if (state->out_fd == -1)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
caps.ac_len = sizeof(caps);
|
||||
caps.ac_type = AUDIO_TYPE_QUERY;
|
||||
caps.ac_subtype = AUDIO_TYPE_QUERY;
|
||||
|
||||
ret = ioctl(fd, AUDIOIOC_GETCAPS, (unsigned long)&caps);
|
||||
if (ret != caps.ac_len)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((caps.ac_controls.b[0] & direction) == 0 ||
|
||||
(caps.ac_format.hw & (1 << (state->format - 1))) == 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
ret = ioctl(fd, AUDIOIOC_RESERVE, (unsigned long)&state->session);
|
||||
#else
|
||||
ret = ioctl(fd, AUDIOIOC_RESERVE, 0);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
cap_desc.session = state->session:
|
||||
#endif
|
||||
cap_desc.caps.ac_len = sizeof(struct audio_caps_s);
|
||||
cap_desc.caps.ac_type = direction;
|
||||
cap_desc.caps.ac_channels = state->chans;
|
||||
cap_desc.caps.ac_chmap = state->chmap;
|
||||
cap_desc.caps.ac_controls.hw[0] = state->samprate;
|
||||
cap_desc.caps.ac_controls.b[3] = state->samprate >> 16;
|
||||
cap_desc.caps.ac_controls.b[2] = state->bpsamp;
|
||||
cap_desc.caps.ac_subtype = state->format;
|
||||
ret = ioctl(fd, AUDIOIOC_CONFIGURE, (unsigned long)&cap_desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -errno;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, AUDIOIOC_REGISTERMQ, (unsigned long)state->mq);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -errno;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, AUDIOIOC_GETBUFFERINFO, (unsigned long)buf_info);
|
||||
if (ret < 0)
|
||||
{
|
||||
buf_info->buffer_size = CONFIG_AUDIO_BUFFER_NUMBYTES;
|
||||
buf_info->nbuffers = CONFIG_AUDIO_NUM_BUFFERS;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int audio_test_start(FAR struct audio_state_s *state, int direction)
|
||||
{
|
||||
int ret = 0;
|
||||
int fd;
|
||||
|
||||
fd = direction == AUDIO_TYPE_OUTPUT ?
|
||||
state->outdev_fd :
|
||||
state->indev_fd;
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
ret = ioctl(fd, AUDIOIOC_START,
|
||||
(unsigned long)state->session);
|
||||
#else
|
||||
ret = ioctl(fd, AUDIOIOC_START, 0);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool audio_test_timeout(FAR struct audio_state_s *state,
|
||||
int direction, struct timeval start)
|
||||
{
|
||||
struct timeval now;
|
||||
struct timeval delta;
|
||||
struct timeval wait;
|
||||
|
||||
if (direction == AUDIO_TYPE_OUTPUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wait.tv_sec = state->duration;
|
||||
wait.tv_usec = 0;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
timersub(&now, &start, &delta);
|
||||
return timercmp(&delta, &wait, >);
|
||||
}
|
||||
|
||||
static int audio_test_stop(FAR struct audio_state_s *state, int direction)
|
||||
{
|
||||
int ret = 0;
|
||||
int fd;
|
||||
|
||||
fd = direction == AUDIO_TYPE_OUTPUT ?
|
||||
state->outdev_fd :
|
||||
state->indev_fd;
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
ret = ioctl(fd, AUDIOIOC_STOP,
|
||||
(unsigned long)state->session);
|
||||
#else
|
||||
ret = ioctl(fd, AUDIOIOC_STOP, 0);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int audio_test_cleanup(FAR struct audio_state_s *state, int direction)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = direction == AUDIO_TYPE_OUTPUT ?
|
||||
state->outdev_fd :
|
||||
state->indev_fd;
|
||||
|
||||
ioctl(fd, AUDIOIOC_UNREGISTERMQ, (unsigned long)state->mq);
|
||||
|
||||
if (state->out_fd >= 0)
|
||||
{
|
||||
close(state->out_fd);
|
||||
state->out_fd = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void audio_test_case(void **audio_state)
|
||||
{
|
||||
FAR struct audio_state_s *state;
|
||||
FAR struct ap_buffer_s **bufs = NULL;
|
||||
struct ap_buffer_info_s buf_info;
|
||||
struct audio_msg_s msg;
|
||||
struct timeval start;
|
||||
int directions[3] =
|
||||
{
|
||||
AUDIO_TYPE_INPUT,
|
||||
AUDIO_TYPE_OUTPUT,
|
||||
-1
|
||||
};
|
||||
|
||||
struct mq_attr attr;
|
||||
unsigned int prio;
|
||||
bool streaming;
|
||||
bool running;
|
||||
int ret = 0;
|
||||
int direct;
|
||||
int x = 0;
|
||||
int i;
|
||||
|
||||
state = (struct audio_state_s *)*audio_state;
|
||||
|
||||
while (directions[x] != -1)
|
||||
{
|
||||
/* first round, test capture.
|
||||
* second round, test playback.
|
||||
* */
|
||||
|
||||
streaming = running = true;
|
||||
if (!(directions[x] & state->direction))
|
||||
{
|
||||
x++;
|
||||
continue;
|
||||
}
|
||||
|
||||
direct = directions[x];
|
||||
|
||||
ret = audio_test_prepare(state, &buf_info, direct);
|
||||
assert_false(ret < 0);
|
||||
|
||||
bufs = (FAR struct ap_buffer_s **)
|
||||
calloc(buf_info.nbuffers, sizeof(FAR void *));
|
||||
assert_true(bufs != NULL);
|
||||
|
||||
ret = audio_test_alloc_buffer(state, bufs, &buf_info, direct);
|
||||
assert_false(ret < 0);
|
||||
|
||||
for (i = 0; i < buf_info.nbuffers; i++)
|
||||
{
|
||||
if (direct == AUDIO_TYPE_OUTPUT)
|
||||
ret = audio_test_readbuffer(state, bufs[i]);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
streaming = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = audio_test_enqueuebuffer(state, bufs[i], direct);
|
||||
assert_false(ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (running)
|
||||
{
|
||||
ret = audio_test_start(state, direct);
|
||||
assert_false(ret < 0);
|
||||
gettimeofday(&start, NULL);
|
||||
}
|
||||
|
||||
printf("Start %s. \n", direct == AUDIO_TYPE_OUTPUT ?
|
||||
"Playback" : "Capture");
|
||||
|
||||
while (running)
|
||||
{
|
||||
ret = mq_receive(state->mq, (FAR char *)&msg, sizeof(msg), &prio);
|
||||
if (ret != sizeof(msg))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (msg.msg_id)
|
||||
{
|
||||
case AUDIO_MSG_DEQUEUE:
|
||||
if (streaming)
|
||||
{
|
||||
if (direct == AUDIO_TYPE_INPUT)
|
||||
{
|
||||
ret = audio_test_writebuffer(state, msg.u.ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = audio_test_readbuffer(state, msg.u.ptr);
|
||||
}
|
||||
|
||||
if (ret != OK)
|
||||
{
|
||||
streaming = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = audio_test_enqueuebuffer(state,
|
||||
msg.u.ptr, direct);
|
||||
if (ret != OK)
|
||||
{
|
||||
close(state->out_fd);
|
||||
state->out_fd = -1;
|
||||
streaming = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_MSG_COMPLETE:
|
||||
running = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Capture stopped */
|
||||
|
||||
if (audio_test_timeout(state, direct, start) || !streaming)
|
||||
{
|
||||
ret = audio_test_stop(state, direct);
|
||||
assert_false(ret < 0);
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ret = mq_getattr(state->mq, &attr);
|
||||
assert_false(ret < 0);
|
||||
|
||||
if (attr.mq_curmsgs == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
mq_receive(state->mq, (FAR char *)&msg, sizeof(msg), &prio);
|
||||
}
|
||||
while (ret >= 0);
|
||||
|
||||
ret = audio_test_free_buffer(state, bufs, &buf_info, direct);
|
||||
assert_false(ret < 0);
|
||||
|
||||
ret = audio_test_cleanup(state, direct);
|
||||
assert_false(ret < 0);
|
||||
|
||||
memset(&buf_info, 0, sizeof(buf_info));
|
||||
free(bufs);
|
||||
bufs = NULL;
|
||||
|
||||
x++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int audio_test_setup(FAR void **audio_state)
|
||||
{
|
||||
FAR struct audio_state_s *state;
|
||||
struct ap_buffer_info_s buf_info;
|
||||
struct mq_attr attr;
|
||||
int maxmsg = 0;
|
||||
int ret = 0;
|
||||
|
||||
state = (struct audio_state_s *)*audio_state;
|
||||
|
||||
if (state->direction & AUDIO_TYPE_OUTPUT)
|
||||
{
|
||||
state->outdev_fd = open(state->outdev, O_RDWR | O_CLOEXEC);
|
||||
assert_false(state->outdev_fd < 0);
|
||||
|
||||
ret = ioctl(state->outdev_fd, AUDIOIOC_GETBUFFERINFO,
|
||||
(unsigned long)&buf_info);
|
||||
maxmsg = MAX(maxmsg,
|
||||
ret >= 0 ? buf_info.nbuffers : CONFIG_AUDIO_NUM_BUFFERS);
|
||||
}
|
||||
|
||||
if (state->direction & AUDIO_TYPE_INPUT)
|
||||
{
|
||||
state->indev_fd = open(state->indev, O_RDWR | O_CLOEXEC);
|
||||
assert_false(state->indev_fd < 0);
|
||||
|
||||
ret = ioctl(state->indev_fd, AUDIOIOC_GETBUFFERINFO,
|
||||
(unsigned long)&buf_info);
|
||||
maxmsg = MAX(maxmsg,
|
||||
ret >= 0 ? buf_info.nbuffers : CONFIG_AUDIO_NUM_BUFFERS);
|
||||
}
|
||||
|
||||
attr.mq_maxmsg = maxmsg + 8;
|
||||
attr.mq_msgsize = sizeof(struct audio_msg_s);
|
||||
attr.mq_curmsgs = 0;
|
||||
attr.mq_flags = 0;
|
||||
|
||||
snprintf(state->mqname, sizeof(state->mqname), "/tmp/%0lx",
|
||||
(unsigned long)((uintptr_t)state));
|
||||
|
||||
state->mq = mq_open(state->mqname, O_RDWR | O_CREAT, 0644, &attr);
|
||||
assert_false(state->mq < 0);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int audio_test_teardown(FAR void **audio_state)
|
||||
{
|
||||
FAR struct audio_state_s *state;
|
||||
state = (struct audio_state_s *)*audio_state;
|
||||
|
||||
if (state->outdev_fd >= 0)
|
||||
{
|
||||
close(state->outdev_fd);
|
||||
state->outdev_fd = -1;
|
||||
}
|
||||
|
||||
if (state->outdev_fd >= 0)
|
||||
{
|
||||
close(state->indev_fd);
|
||||
state->indev_fd = -1;
|
||||
}
|
||||
|
||||
mq_close(state->mq);
|
||||
mq_unlink(state->mqname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: loopback_test_main
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, FAR char *argv[])
|
||||
{
|
||||
struct audio_state_s state = {
|
||||
.outdev = "/dev/audio/pcm0p",
|
||||
.indev = "/dev/audio/pcm0c",
|
||||
.duration = 10,
|
||||
.chans = 2,
|
||||
.bpsamp = 16,
|
||||
.samprate = 44100,
|
||||
.format = AUDIO_FMT_PCM,
|
||||
.chmap = 0,
|
||||
.outdev_fd = -1,
|
||||
.indev_fd = -1,
|
||||
.out_fd = -1,
|
||||
};
|
||||
|
||||
parse_commandline(&state, argc, argv);
|
||||
|
||||
const struct CMUnitTest tests[] =
|
||||
{
|
||||
cmocka_unit_test_prestate_setup_teardown(audio_test_case,
|
||||
audio_test_setup,
|
||||
audio_test_teardown,
|
||||
&state),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user