Updated audio subsystem from Ken Pettit
This commit is contained in:
parent
70a191159b
commit
8048001c5e
156
audio/Kconfig
156
audio/Kconfig
@ -11,22 +11,139 @@ config AUDIO
|
||||
|
||||
if AUDIO
|
||||
|
||||
config AUDIO_NCHANNELS
|
||||
int "Number of Audio Channels"
|
||||
default 2
|
||||
config AUDIO_MULTI_SESSION
|
||||
bool "Support multiple sessions"
|
||||
default n
|
||||
---help---
|
||||
Stereo channel support is standard, but some systems may support 5 or 7
|
||||
channel capability.
|
||||
Some audio devices, such as USB attached sound cards, may support more
|
||||
than one streaming session at a time (each with one or more audio channels).
|
||||
Selecting this feature adds support for tracking multiple concurrent
|
||||
sessions with the lower-level audio devices.
|
||||
|
||||
config AUDIO_LARGE_BUFFERS
|
||||
bool "Support Audio Buffers with greater than 65K samples"
|
||||
default n
|
||||
---help---
|
||||
By default, the Audio Pipeline Buffer uses a 16-bit max sample count, limiting
|
||||
By default, the Audio Pipeline Buffers use a 16-bit max sample count, limiting
|
||||
the number of samples per buffer to 65K. Enable this option to specify a
|
||||
32-bit max sample count for increased samples / buffer capability.
|
||||
channel capability.
|
||||
|
||||
config AUDIO_NUM_BUFFERS
|
||||
int "Number of buffers for audio processing"
|
||||
default 2
|
||||
---help---
|
||||
Specifies the number of buffers to allocate for audio processing.
|
||||
If Driver Specified buffer sizes is enabled (below), then the
|
||||
low-level drivers will have the opportunity to override this
|
||||
value.
|
||||
|
||||
config AUDIO_BUFFER_NUMBYTES
|
||||
int "Size of each audio buffer for audio processing"
|
||||
default 8192
|
||||
---help---
|
||||
Specifies the allocation size for each audio buffer
|
||||
If Driver Specified buffer sizes is enabled (below), then the
|
||||
low-level drivers will have the opportunity to override this
|
||||
value.
|
||||
|
||||
config AUDIO_DRIVER_SPECIFIC_BUFFERS
|
||||
bool "Support for Driver specified buffer sizes"
|
||||
default n
|
||||
---help---
|
||||
By default, the Audio system uses the same size and number of buffers
|
||||
regardless of the specific audio device in use. Specifying 'y' here
|
||||
adds extra code which allows the lower-level audio device to specify
|
||||
a partucular size and number of buffers.
|
||||
|
||||
menu "Supported Audio Formats"
|
||||
|
||||
config AUDIO_FORMAT_AC3
|
||||
bool "AC3 Format"
|
||||
default n
|
||||
---help---
|
||||
Build in support for AC3 (Dolby Digital) Audio format.
|
||||
|
||||
config AUDIO_FORMAT_DTS
|
||||
bool "DTS Format"
|
||||
default n
|
||||
---help---
|
||||
Add in support for DTS format.
|
||||
|
||||
config AUDIO_FORMAT_PCM
|
||||
bool "PCM Audio"
|
||||
default y
|
||||
---help---
|
||||
Build in support for PCM Audio format.
|
||||
|
||||
config AUDIO_FORMAT_MP3
|
||||
bool "MPEG 3 Layer 1"
|
||||
default y
|
||||
---help---
|
||||
Build in support for MP3 Audio format.
|
||||
|
||||
config AUDIO_FORMAT_MIDI
|
||||
bool "Midi Format"
|
||||
default n
|
||||
---help---
|
||||
Add in support for MIDI format.
|
||||
|
||||
config AUDIO_FORMAT_WMA
|
||||
bool "WMA Format (see copyright notice)"
|
||||
default n
|
||||
---help---
|
||||
Add in support for Microsoft Windows Media format.
|
||||
|
||||
config AUDIO_FORMAT_OGG_VORBIS
|
||||
bool "Ogg Vorbis format"
|
||||
default n
|
||||
---help---
|
||||
Build in support for the Open Source Ogg Vorbis format.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Exclude Specific Audio Features"
|
||||
|
||||
config AUDIO_EXCLUDE_VOLUME
|
||||
bool "Exclude volume controls"
|
||||
default n
|
||||
---help---
|
||||
Exclude building support for changing the playback volume.
|
||||
|
||||
config AUDIO_EXCLUDE_BALANCE
|
||||
bool "Exclude balance controls"
|
||||
default n
|
||||
---help---
|
||||
Exclude building support for changing the balance.
|
||||
|
||||
config AUDIO_EXCLUDE_TONE
|
||||
bool "Exclude tone (bass and treble) controls"
|
||||
default n
|
||||
---help---
|
||||
Exclude building support for changing the bass and treble.
|
||||
|
||||
config AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
bool "Exclude pause and resume controls"
|
||||
default n
|
||||
---help---
|
||||
Exclude building support for pausing and resuming audio files
|
||||
once they are submitted. If the sound system is being used to play
|
||||
short system notification or error type sounds that typicaly only
|
||||
last a second or two, then there is no need (or chance) to pause or
|
||||
resume sound playback once it has started.
|
||||
|
||||
config AUDIO_EXCLUDE_STOP
|
||||
bool "Exclude stop playback controls"
|
||||
default n
|
||||
---help---
|
||||
Exclude building support for stopping audio files once they are
|
||||
submitted. If the sound system is being used to play short ssytem
|
||||
notification or error type sounds that typicaly only last a second
|
||||
or two, then there is no need (or chance) to stop the sound
|
||||
playback once it has started.
|
||||
|
||||
endmenu
|
||||
|
||||
config AUDIO_CUSTOM_DEV_PATH
|
||||
bool "Use custom device path"
|
||||
default n
|
||||
@ -57,33 +174,6 @@ config AUDIO_DEV_PATH
|
||||
endif
|
||||
endif
|
||||
|
||||
menu "Supported Audio Formats"
|
||||
|
||||
config AUDIO_FORMAT_PCM
|
||||
bool "PCM Audio"
|
||||
default y
|
||||
---help---
|
||||
Build in support for PCM Audio format.
|
||||
|
||||
config AUDIO_FORMAT_MP3
|
||||
bool "MPEG 3 Layer 1"
|
||||
default n
|
||||
---help---
|
||||
Build in support for MP3 Audio format.
|
||||
|
||||
config AUDIO_FORMAT_WMA
|
||||
bool "WMA Format (see copyright notice)"
|
||||
default n
|
||||
---help---
|
||||
Add in support for Microsoft Windows Media format.
|
||||
|
||||
config AUDIO_FORMAT_OGG_VORBIS
|
||||
bool "Ogg Vorbis format"
|
||||
default n
|
||||
---help---
|
||||
Build in support for the Open Source Ogg Vorbis format.
|
||||
|
||||
endmenu
|
||||
|
||||
# These are here as placeholders of what could be added
|
||||
|
||||
|
@ -53,18 +53,6 @@ ifeq ($(CONFIG_AUDIO_FORMAT_PCM),y)
|
||||
CSRCS += pcm.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AUDIO_MIXER),y)
|
||||
CSRCS += mixer.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AUDIO_MIDI_SYNTH),y)
|
||||
CSRCS += midisynth.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AUDIO_FONT),y)
|
||||
CSRCS += audio_font.c
|
||||
endif
|
||||
|
||||
AOBJS = $(ASRCS:.S=$(OBJEXT))
|
||||
COBJS = $(CSRCS:.c=$(OBJEXT))
|
||||
|
||||
|
125
audio/README.txt
Normal file
125
audio/README.txt
Normal file
@ -0,0 +1,125 @@
|
||||
README
|
||||
^^^^^^
|
||||
|
||||
This directory contains the audio subsytem support for NuttX. The contents of this
|
||||
directory are only built if CONFIG_AUDIO is defined in the NuttX configuration file.
|
||||
|
||||
Contents
|
||||
^^^^^^^^
|
||||
- Files in this directory
|
||||
- Related Header Files
|
||||
- Related directories
|
||||
|
||||
Files in this directory
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This directory holds the NuttX audio subsystem upper-half. The upper-half provides
|
||||
a common interface for applications to interface with and also defines a bind
|
||||
layer for specific lower-half audio device drivers.
|
||||
|
||||
audio.c - The upper-half driver that binds to a lower-half driver from the
|
||||
drivers/audio subdirectory. For each attached audio device, there
|
||||
will be an instance of this upper-half driver bound to the
|
||||
instance of the lower half driver context.
|
||||
buffer.c - Routines to manage creattion and destruction of audio pipeline buffers
|
||||
(apb) used in the audio subsystem. Audio pipeline buffers are passed
|
||||
between user applications and the audio drivers to deliver audio
|
||||
content for playback (or possibly recording in the future).
|
||||
pcm.c - Routines to manage PCM / WAV type data. Currently just a placeholder.
|
||||
README - This file!
|
||||
|
||||
|
||||
Related Header Files
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
include/nuttx/audio/audio.h -- Top level include file defining the audio interface
|
||||
include/nuttx/audio/vs1053.h -- Specific driver initialization prototypes
|
||||
|
||||
Configuration Settings
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
General Audio Settings
|
||||
----------------------
|
||||
|
||||
CONFIG_AUDIO
|
||||
Enables overall support for audio subsystem
|
||||
CONFIG_AUDIO_MULTI_SESSION
|
||||
Enables support for the audio subystem to track mutliple open sessions
|
||||
with lower-level audio devices.
|
||||
CONFIG_AUDIO_LARGE_BUFFERS
|
||||
Specifies that buffer size variables should be 32-bit vs. the normal 16-bit
|
||||
size. This allows buffers to be larger than 64K bytes on systems with
|
||||
an abundance of RAM.
|
||||
CONFIG_AUDIO_NUM_BUFFERS
|
||||
Sets the number of audio buffers to use for audio operations. If the
|
||||
configuration has set CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS, and an audio
|
||||
device does not support the operation, then this becomes the default number
|
||||
of buffers to use.
|
||||
CONFIG_AUDIO_BUFFER_SIZE
|
||||
Sets the size of the audio buffers to use for audio operations. If the
|
||||
configuration has set CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS, and an audio
|
||||
device does not support the operation, then this becomes the default size
|
||||
of buffers to use.
|
||||
CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS
|
||||
Enables support for lower-level audio drivers to specify the number and size
|
||||
of buffers that should be allocated for best performance while interacting
|
||||
with that driver.
|
||||
CONFIG_AUDIO_CUSTOM_DEV_PATH
|
||||
Specifies that all audio devices should be registered in the filesystem at
|
||||
a location other than the standard /dev/audio directory.
|
||||
CONFIG_AUDIO_DEV_ROOT
|
||||
Specifies that all audio devices should be registered in the /dev directory.
|
||||
Saves a tiny bit of code and RAM space since an additional directory isn't needed,
|
||||
but at the expense of execution speed when searching for audio devices since all
|
||||
entries in /dev must be opened and tested if they provide audio support.
|
||||
Available only if CONFIG_AUDIO_CUSTOM_DEV_PATH is selected.
|
||||
CONFIG_AUDIO_DEV_PATH
|
||||
Specifies a custom directory where audio devices will be registered.
|
||||
Available if CONFIG_AUDIO_CUSTOM_DEV_PATH is selected and CONFIG_AUDIO_DEV_ROOT
|
||||
is not selected.
|
||||
|
||||
|
||||
Audio Format Support Selections
|
||||
-------------------------------
|
||||
|
||||
CONFIG_AUDIO_FORMAT_AC3
|
||||
Specifies that AC3 support should be enabled if available by a lower-half driver.
|
||||
CONFIG_AUDIO_FORMAT_DTS
|
||||
Specifies that DTS support should be enabled if available by a lower-half driver.
|
||||
CONFIG_AUDIO_FORMAT_PCM
|
||||
Specifies that PCM support should be enabled if available by a lower-half driver.
|
||||
CONFIG_AUDIO_FORMAT_MP3
|
||||
Specifies that MP3 support should be enabled if available by a lower-half driver.
|
||||
CONFIG_AUDIO_FORMAT_MIDI
|
||||
Specifies that MIDI support should be enabled if available by a lower-half driver.
|
||||
CONFIG_AUDIO_FORMAT_WMA
|
||||
Specifies that WMA support should be enabled if available by a lower-half driver.
|
||||
CONFIG_AUDIO_FORMAT_OGG_VORBIS
|
||||
Specifies that Ogg Vorbis support should be enabled if available by a lower-half driver.
|
||||
|
||||
|
||||
Audio feature exclusion Selections
|
||||
----------------------------------
|
||||
|
||||
CONFIG_AUDIO_EXCLUDE_VOLUME
|
||||
Disables support in all libraries and drivers for setting the playback volume. In
|
||||
this case, the device volume will depend on the default level defined by the
|
||||
lower-level driver, typically via a config setting.
|
||||
CONFIG_AUDIO_EXCLUDE_BALANCE
|
||||
Disables support in all libraries and drivers for setting the playback balance.
|
||||
Also, the volume support must not be excluded for balance to work or make sense.
|
||||
CONFIG_AUDIO_EXCLUDE_TONE
|
||||
Disables support for setting bass and treble.
|
||||
CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
Disables support in all libraries and drivers for pausing and resuming playback.
|
||||
CONFIG_AUDIO_EXCLUDE_STOP
|
||||
Disables support in all libraries and drivers for stopping an audio playback
|
||||
once it has started. Typically selected if only short notification audio sounds
|
||||
are needed (vs. media playing type applications).
|
||||
|
||||
Related Subdirectories
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
drivers/audio -- Contains the lower-level device specific drivers.
|
||||
apps/system/nxplayer -- User-mode audio subsystem interface library.
|
||||
|
570
audio/audio.c
570
audio/audio.c
@ -60,6 +60,7 @@
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/audio/audio.h>
|
||||
#include <mqueue.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
|
||||
@ -75,6 +76,10 @@
|
||||
# define AUDIO_MAX_DEVICE_PATH 32
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO
|
||||
# define CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO 1
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Definitions
|
||||
****************************************************************************/
|
||||
@ -84,10 +89,10 @@
|
||||
struct audio_upperhalf_s
|
||||
{
|
||||
uint8_t crefs; /* The number of times the device has been opened */
|
||||
volatile bool started; /* True: pulsed output is being generated */
|
||||
volatile bool started; /* True: playback is active */
|
||||
sem_t exclsem; /* Supports mutual exclusion */
|
||||
struct audio_info_s info; /* Pulsed output characteristics */
|
||||
FAR struct audio_lowerhalf_s *dev; /* lower-half state */
|
||||
mqd_t usermq; /* User mode app's message queue */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -98,10 +103,16 @@ static int audio_open(FAR struct file *filep);
|
||||
static int audio_close(FAR struct file *filep);
|
||||
static ssize_t audio_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
|
||||
static ssize_t audio_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
|
||||
static int audio_start(FAR struct audio_upperhalf_s *upper, unsigned int oflags);
|
||||
static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int audio_start(FAR struct audio_upperhalf_s *upper, FAR void *session);
|
||||
static void audio_callback(FAR void *priv, uint16_t reason,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status, FAR void *session);
|
||||
#else
|
||||
static int audio_start(FAR struct audio_upperhalf_s *upper);
|
||||
static void audio_callback(FAR void *priv, uint16_t reason,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status);
|
||||
#endif /* CONFIG_AUDIO_MULTI_SESSION */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@ -113,10 +124,10 @@ static const struct file_operations g_audioops =
|
||||
audio_close, /* close */
|
||||
audio_read, /* read */
|
||||
audio_write, /* write */
|
||||
0, /* seek */
|
||||
0, /* seek */
|
||||
audio_ioctl /* ioctl */
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
, 0 /* poll */
|
||||
, 0 /* poll */
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -134,10 +145,10 @@ static const struct file_operations g_audioops =
|
||||
|
||||
static int audio_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct audio_upperhalf_s *upper = inode->i_private;
|
||||
uint8_t tmp;
|
||||
int ret;
|
||||
uint8_t tmp;
|
||||
int ret;
|
||||
|
||||
audvdbg("crefs: %d\n", upper->crefs);
|
||||
|
||||
@ -167,6 +178,7 @@ static int audio_open(FAR struct file *filep)
|
||||
/* Save the new open count on success */
|
||||
|
||||
upper->crefs = tmp;
|
||||
upper->usermq = NULL;
|
||||
ret = OK;
|
||||
|
||||
errout_with_sem:
|
||||
@ -186,9 +198,9 @@ errout:
|
||||
|
||||
static int audio_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct audio_upperhalf_s *upper = inode->i_private;
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
audvdbg("crefs: %d\n", upper->crefs);
|
||||
|
||||
@ -243,7 +255,18 @@ errout:
|
||||
|
||||
static ssize_t audio_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
|
||||
{
|
||||
/* Return zero -- usually meaning end-of-file */
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct audio_upperhalf_s *upper = inode->i_private;
|
||||
FAR struct audio_lowerhalf_s *lower = upper->dev;
|
||||
|
||||
/* TODO: Should we check permissions here? */
|
||||
|
||||
/* Audio read operations get passed directly to the lower-level */
|
||||
|
||||
if (lower->ops->read != NULL)
|
||||
{
|
||||
return lower->ops->read(lower, buffer, buflen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -258,6 +281,19 @@ static ssize_t audio_read(FAR struct file *filep, FAR char *buffer, size_t bufle
|
||||
|
||||
static ssize_t audio_write(FAR struct file *filep, FAR const char *buffer, size_t buflen)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct audio_upperhalf_s *upper = inode->i_private;
|
||||
FAR struct audio_lowerhalf_s *lower = upper->dev;
|
||||
|
||||
/* TODO: Should we check permissions here? */
|
||||
|
||||
/* Audio write operations get passed directly to the lower-level */
|
||||
|
||||
if (lower->ops->write != NULL)
|
||||
{
|
||||
return lower->ops->write(lower, buffer, buflen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -269,7 +305,11 @@ static ssize_t audio_write(FAR struct file *filep, FAR const char *buffer, size_
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
static int audio_start(FAR struct audio_upperhalf_s *upper, unsigned int oflags)
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int audio_start(FAR struct audio_upperhalf_s *upper, FAR void *session)
|
||||
#else
|
||||
static int audio_start(FAR struct audio_upperhalf_s *upper)
|
||||
#endif
|
||||
{
|
||||
FAR struct audio_lowerhalf_s *lower = upper->dev;
|
||||
int ret = OK;
|
||||
@ -280,17 +320,21 @@ static int audio_start(FAR struct audio_upperhalf_s *upper, unsigned int oflags)
|
||||
|
||||
if (!upper->started)
|
||||
{
|
||||
/* Invoke the bottom half method to start the pulse train */
|
||||
/* Invoke the bottom half method to start the audio stream */
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
ret = lower->ops->start(lower, session);
|
||||
#else
|
||||
ret = lower->ops->start(lower);
|
||||
#endif
|
||||
|
||||
/* A return value of zero means that the pulse train was started
|
||||
/* A return value of zero means that the audio stream was started
|
||||
* successfully.
|
||||
*/
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Indicate that the pulse train has started */
|
||||
/* Indicate that the audio stream has started */
|
||||
|
||||
upper->started = true;
|
||||
}
|
||||
@ -309,10 +353,14 @@ static int audio_start(FAR struct audio_upperhalf_s *upper, unsigned int oflags)
|
||||
|
||||
static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct audio_upperhalf_s *upper = inode->i_private;
|
||||
FAR struct audio_lowerhalf_s *lower = upper->dev;
|
||||
int ret;
|
||||
FAR struct audio_buf_desc_s *bufdesc;
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
FAR void *session;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
audvdbg("cmd: %d arg: %ld\n", cmd, arg);
|
||||
|
||||
@ -347,14 +395,19 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
|
||||
case AUDIOIOC_CONFIGURE:
|
||||
{
|
||||
FAR const struct audio_caps_s *caps = (FAR const struct audio_caps_s*)((uintptr_t)arg);
|
||||
FAR const struct audio_caps_desc_s *caps =
|
||||
(FAR const struct audio_caps_desc_s*)((uintptr_t)arg);
|
||||
DEBUGASSERT(lower->ops->configure != NULL);
|
||||
|
||||
audvdbg("AUDIOIOC_INITIALIZE: Device=%d", caps->ac_type);
|
||||
audvdbg("AUDIOIOC_INITIALIZE: Device=%d", caps->caps.ac_type);
|
||||
|
||||
/* Call the lower-half driver configure handler */
|
||||
|
||||
ret = lower->ops->configure(lower, caps, &audio_callback, upper);
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
ret = lower->ops->configure(lower, caps->session, &caps->caps);
|
||||
#else
|
||||
ret = lower->ops->configure(lower, &caps->caps);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
@ -369,10 +422,10 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
}
|
||||
break;
|
||||
|
||||
/* AUDIOIOC_START - Start the pulsed output. The AUDIOIOC_SETCHARACTERISTICS
|
||||
/* AUDIOIOC_START - Start the audio stream. The AUDIOIOC_SETCHARACTERISTICS
|
||||
* command must have previously been sent.
|
||||
*
|
||||
* ioctl argument: None
|
||||
* ioctl argument: Audio session
|
||||
*/
|
||||
|
||||
case AUDIOIOC_START:
|
||||
@ -380,17 +433,23 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
audvdbg("AUDIOIOC_START\n");
|
||||
DEBUGASSERT(lower->ops->start != NULL);
|
||||
|
||||
/* Start the pulse train */
|
||||
/* Start the audio stream */
|
||||
|
||||
ret = audio_start(upper, filep->f_oflags);
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
session = (FAR void *) arg;
|
||||
ret = audio_start(upper, session);
|
||||
#else
|
||||
ret = audio_start(upper);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
/* AUDIOIOC_STOP - Stop the pulsed output.
|
||||
/* AUDIOIOC_STOP - Stop the audio stream.
|
||||
*
|
||||
* ioctl argument: None
|
||||
* ioctl argument: Audio session
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
case AUDIOIOC_STOP:
|
||||
{
|
||||
audvdbg("AUDIOIOC_STOP\n");
|
||||
@ -398,11 +457,191 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
|
||||
if (upper->started)
|
||||
{
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
session = (FAR void *) arg;
|
||||
ret = lower->ops->stop(lower, session);
|
||||
#else
|
||||
ret = lower->ops->stop(lower);
|
||||
#endif
|
||||
upper->started = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* CONFIG_AUDIO_EXCLUDE_STOP */
|
||||
|
||||
/* AUDIOIOC_PAUSE - Pause the audio stream.
|
||||
*
|
||||
* ioctl argument: Audio session
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
|
||||
case AUDIOIOC_PAUSE:
|
||||
{
|
||||
audvdbg("AUDIOIOC_PAUSE\n");
|
||||
DEBUGASSERT(lower->ops->pause != NULL);
|
||||
|
||||
if (upper->started)
|
||||
{
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
session = (FAR void *) arg;
|
||||
ret = lower->ops->pause(lower, session);
|
||||
#else
|
||||
ret = lower->ops->pause(lower);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* AUDIOIOC_RESUME - Resume the audio stream.
|
||||
*
|
||||
* ioctl argument: Audio session
|
||||
*/
|
||||
|
||||
case AUDIOIOC_RESUME:
|
||||
{
|
||||
audvdbg("AUDIOIOC_RESUME\n");
|
||||
DEBUGASSERT(lower->ops->resume != NULL);
|
||||
|
||||
if (upper->started)
|
||||
{
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
session = (FAR void *) arg;
|
||||
ret = lower->ops->resume(lower, session);
|
||||
#else
|
||||
ret = lower->ops->resume(lower);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */
|
||||
|
||||
/* AUDIOIOC_ALLOCBUFFER - Allocate an audio buffer
|
||||
*
|
||||
* ioctl argument: pointer to an audio_buf_desc_s structure
|
||||
*/
|
||||
|
||||
case AUDIOIOC_ALLOCBUFFER:
|
||||
{
|
||||
audvdbg("AUDIOIOC_ALLOCBUFFER\n");
|
||||
|
||||
bufdesc = (FAR struct audio_buf_desc_s *) arg;
|
||||
if (lower->ops->allocbuffer)
|
||||
{
|
||||
ret = lower->ops->allocbuffer(lower, bufdesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Perform a simple kumalloc operation assuming 1 session */
|
||||
|
||||
ret = apb_alloc(bufdesc);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* AUDIOIOC_FREEBUFFER - Free an audio buffer
|
||||
*
|
||||
* ioctl argument: pointer to an audio_buf_desc_s structure
|
||||
*/
|
||||
|
||||
case AUDIOIOC_FREEBUFFER:
|
||||
{
|
||||
audvdbg("AUDIOIOC_FREEBUFFER\n");
|
||||
|
||||
bufdesc = (FAR struct audio_buf_desc_s *) arg;
|
||||
if (lower->ops->freebuffer)
|
||||
{
|
||||
ret = lower->ops->freebuffer(lower, bufdesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Perform a simple kufree operation */
|
||||
|
||||
DEBUGASSERT(bufdesc->u.pBuffer != NULL);
|
||||
apb_free(bufdesc->u.pBuffer);
|
||||
ret = sizeof(struct audio_buf_desc_s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* AUDIOIOC_ENQUEUEBUFFER - Enqueue an audio buffer
|
||||
*
|
||||
* ioctl argument: pointer to an audio_buf_desc_s structure
|
||||
*/
|
||||
|
||||
case AUDIOIOC_ENQUEUEBUFFER:
|
||||
{
|
||||
audvdbg("AUDIOIOC_ENQUEUEBUFFER\n");
|
||||
|
||||
DEBUGASSERT(lower->ops->enqueuebuffer != NULL);
|
||||
|
||||
bufdesc = (FAR struct audio_buf_desc_s *) arg;
|
||||
ret = lower->ops->enqueuebuffer(lower, bufdesc->u.pBuffer);
|
||||
}
|
||||
break;
|
||||
|
||||
/* AUDIOIOC_REGISTERMQ - Register a client Message Queue
|
||||
*
|
||||
* TODO: This needs to have multi session support.
|
||||
*/
|
||||
|
||||
case AUDIOIOC_REGISTERMQ:
|
||||
{
|
||||
upper->usermq = (mqd_t) arg;
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
/* AUDIOIOC_UNREGISTERMQ - Register a client Message Queue
|
||||
*
|
||||
* TODO: This needs to have multi session support.
|
||||
*/
|
||||
|
||||
case AUDIOIOC_UNREGISTERMQ:
|
||||
{
|
||||
upper->usermq = NULL;
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
/* AUDIOIOC_RESERVE - Reserve a session with the driver
|
||||
*
|
||||
* ioctl argument - pointer to receive the session context
|
||||
*/
|
||||
|
||||
case AUDIOIOC_RESERVE:
|
||||
{
|
||||
DEBUGASSERT(lower->ops->reserve != NULL);
|
||||
|
||||
/* Call lower-half to perform the reservation */
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
ret = lower->ops->reserve(lower, (FAR void **) arg);
|
||||
#else
|
||||
ret = lower->ops->reserve(lower);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
/* AUDIOIOC_RESERVE - Reserve a session with the driver
|
||||
*
|
||||
* ioctl argument - pointer to receive the session context
|
||||
*/
|
||||
|
||||
case AUDIOIOC_RELEASE:
|
||||
{
|
||||
DEBUGASSERT(lower->ops->release != NULL);
|
||||
|
||||
/* Call lower-half to perform the release */
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
ret = lower->ops->release(lower, (FAR void *) arg);
|
||||
#else
|
||||
ret = lower->ops->release(lower);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
/* Any unrecognized IOCTL commands might be platform-specific ioctl commands */
|
||||
|
||||
@ -419,6 +658,182 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: audio_dequeuebuffer
|
||||
*
|
||||
* Description:
|
||||
* Dequeues a previously enqueued Audio Pipeline Buffer.
|
||||
*
|
||||
* 1. The upper half driver calls the enqueuebuffer method, providing the
|
||||
* lower half driver with the ab_buffer to process.
|
||||
* 2. The lower half driver's enqueuebuffer will either processes the
|
||||
* buffer directly, or more likely add it to a queue for processing
|
||||
* by a background thread or worker task.
|
||||
* 3. When the lower half driver has completed processing of the enqueued
|
||||
* ab_buffer, it will call this routine to indicate processing of the
|
||||
* buffer is complete.
|
||||
* 4. When this routine is called, it will check if any threads are waiting
|
||||
* to enqueue additional buffers and "wake them up" for further
|
||||
* processing.
|
||||
*
|
||||
* Input parameters:
|
||||
* handle - This is the handle that was provided to the lower-half
|
||||
* start() method.
|
||||
* apb - A pointer to the previsously enqueued ap_buffer_s
|
||||
* status - Status of the dequeue operation
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This function may be called from an interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status,
|
||||
FAR void *session)
|
||||
#else
|
||||
static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status)
|
||||
#endif
|
||||
{
|
||||
struct audio_msg_s msg;
|
||||
|
||||
audllvdbg("Entry\n");
|
||||
|
||||
/* Send a dequeue message to the user if a message queue is registered */
|
||||
|
||||
if (upper->usermq != NULL)
|
||||
{
|
||||
msg.msgId = AUDIO_MSG_DEQUEUE;
|
||||
msg.u.pPtr = apb;
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
msg.session = session;
|
||||
#endif
|
||||
apb->flags |= AUDIO_APB_DEQUEUED;
|
||||
mq_send(upper->usermq, &msg, sizeof(msg), CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: audio_complete
|
||||
*
|
||||
* Description:
|
||||
* Send an AUDIO_MSG_COMPLETE message to the client to indicate that the
|
||||
* active playback has completed. The lower-half driver initiates this
|
||||
* call via its callback pointer to our upper-half driver.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static inline void audio_complete(FAR struct audio_upperhalf_s *upper,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status,
|
||||
FAR void *session)
|
||||
#else
|
||||
static inline void audio_complete(FAR struct audio_upperhalf_s *upper,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status)
|
||||
#endif
|
||||
{
|
||||
struct audio_msg_s msg;
|
||||
|
||||
audllvdbg("Entry\n");
|
||||
|
||||
/* Send a dequeue message to the user if a message queue is registered */
|
||||
|
||||
upper->started = false;
|
||||
if (upper->usermq != NULL)
|
||||
{
|
||||
msg.msgId = AUDIO_MSG_COMPLETE;
|
||||
msg.u.pPtr = NULL;
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
msg.session = session;
|
||||
#endif
|
||||
mq_send(upper->usermq, &msg, sizeof(msg),
|
||||
CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: audio_callback
|
||||
*
|
||||
* Description:
|
||||
* Provides a callback interface for lower-half drivers to call to the
|
||||
* upper-half for buffer dequeueing, error reporting, etc.
|
||||
*
|
||||
* Input parameters:
|
||||
* priv - Private context data owned by the upper-half
|
||||
* reason - The reason code for the callback
|
||||
* apb - A pointer to the previsously enqueued ap_buffer_s
|
||||
* status - Status information associated with the callback
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This function may be called from an interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static void audio_callback(FAR void *handle, uint16_t reason,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status,
|
||||
FAR void *session)
|
||||
#else
|
||||
static void audio_callback(FAR void *handle, uint16_t reason,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status)
|
||||
#endif
|
||||
{
|
||||
FAR struct audio_upperhalf_s *upper = (FAR struct audio_upperhalf_s *)handle;
|
||||
|
||||
audllvdbg("Entry\n");
|
||||
|
||||
/* Perform operation based on reason code */
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
case AUDIO_CALLBACK_DEQUEUE:
|
||||
{
|
||||
/* Call the dequeue routine */
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
audio_dequeuebuffer(upper, apb, status, session);
|
||||
#else
|
||||
audio_dequeuebuffer(upper, apb, status);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
/* Lower-half I/O error occurred */
|
||||
|
||||
case AUDIO_CALLBACK_IOERR:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
/* Lower-half driver has completed a playback */
|
||||
|
||||
case AUDIO_CALLBACK_COMPLETE:
|
||||
{
|
||||
/* Send a complete message to the user if a message queue is registered */
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
audio_complete(upper, apb, status, session);
|
||||
#else
|
||||
audio_complete(upper, apb, status);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
auddbg("Unknown callback reason code %d\n", reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -451,14 +866,14 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev)
|
||||
{
|
||||
FAR struct audio_upperhalf_s *upper;
|
||||
char path[AUDIO_MAX_DEVICE_PATH];
|
||||
char path[AUDIO_MAX_DEVICE_PATH];
|
||||
static bool dev_audio_created = false;
|
||||
#ifndef CONFIG_AUDIO_CUSTOM_DEV_PATH
|
||||
const char* devname = "/dev/audio";
|
||||
#elif !defined(CONFIG_AUDIO_DEV_ROOT)
|
||||
const char* devname = CONFIG_AUDIO_DEV_PATH;
|
||||
const char* ptr;
|
||||
char* pathptr;
|
||||
char* pathptr;
|
||||
#endif
|
||||
|
||||
/* Allocate the upper-half data structure */
|
||||
@ -570,102 +985,13 @@ int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev)
|
||||
strncat(path, name, AUDIO_MAX_DEVICE_PATH - 11);
|
||||
#endif
|
||||
|
||||
/* Give the lower-half a context to the upper half */
|
||||
|
||||
dev->upper = audio_callback;
|
||||
dev->priv = upper;
|
||||
|
||||
audvdbg("Registering %s\n", path);
|
||||
return register_driver(path, &g_audioops, 0666, upper);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: audio_dequeuebuffer
|
||||
*
|
||||
* Description:
|
||||
* Dequeues a previously enqueued Audio Pipeline Buffer.
|
||||
*
|
||||
* 1. The upper half driver calls the enqueuebuffer method, providing the
|
||||
* lower half driver with the ab_buffer to process.
|
||||
* 2. The lower half driver's enqueuebuffer will either processes the
|
||||
* buffer directly, or more likely add it to a queue for processing
|
||||
* by a background thread or worker task.
|
||||
* 3. When the lower half driver has completed processing of the enqueued
|
||||
* ab_buffer, it will call this routine to indicated processing of the
|
||||
* buffer is complete.
|
||||
* 4. When this routine is called, it will check if any threads are waiting
|
||||
* to enqueue additional buffers and "wake them up" for further
|
||||
* processing.
|
||||
*
|
||||
* Input parameters:
|
||||
* handle - This is the handle that was provided to the lower-half
|
||||
* start() method.
|
||||
* apb - A pointer to the previsously enqueued ap_buffer_s
|
||||
* status - Status of the dequeue operation
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This function may be called from an interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status)
|
||||
{
|
||||
audllvdbg("Entry\n");
|
||||
|
||||
/* TODO: Implement the logic */
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: audio_callback
|
||||
*
|
||||
* Description:
|
||||
* Provides a callback interface for lower-half drivers to call to the
|
||||
* upper-half for buffer dequeueing, error reporting, etc.
|
||||
*
|
||||
* Input parameters:
|
||||
* priv - Private context data owned by the upper-half
|
||||
* reason - The reason code for the callback
|
||||
* apb - A pointer to the previsously enqueued ap_buffer_s
|
||||
* status - Status information associated with the callback
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This function may be called from an interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void audio_callback(FAR void *handle, uint16_t reason,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status)
|
||||
{
|
||||
FAR struct audio_upperhalf_s *upper = (FAR struct audio_upperhalf_s *)handle;
|
||||
|
||||
audllvdbg("Entry\n");
|
||||
|
||||
/* Perform operation based on reason code */
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
case AUDIO_CALLBACK_DEQUEUE:
|
||||
{
|
||||
/* Call the dequeue routine */
|
||||
|
||||
audio_dequeuebuffer(upper, apb, status);
|
||||
break;
|
||||
}
|
||||
|
||||
case AUDIO_CALLBACK_IOERR:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
auddbg("Unknown callback reason code %d\n", reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_AUDIO */
|
||||
|
@ -84,11 +84,11 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void apb_semtake(sem_t *sem)
|
||||
static void apb_semtake(FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
/* Take the semaphore (perhaps waiting) */
|
||||
|
||||
while (sem_wait(sem) != 0)
|
||||
while (sem_wait(&apb->sem) != 0)
|
||||
{
|
||||
/* The only case that an error should occr here is if
|
||||
* the wait was awakened by a signal.
|
||||
@ -102,7 +102,7 @@ static void apb_semtake(sem_t *sem)
|
||||
* Name: apb_semgive
|
||||
****************************************************************************/
|
||||
|
||||
#define apb_semgive(s) sem_post(s)
|
||||
#define apb_semgive(b) sem_post(&b->sem)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: apb_alloc
|
||||
@ -113,11 +113,41 @@ static void apb_semtake(sem_t *sem)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct ap_buffer_s *apb_alloc(int type, int sampleCount)
|
||||
int apb_alloc(FAR struct audio_buf_desc_s * bufdesc)
|
||||
{
|
||||
/* TODO: Implement the alloc logic */
|
||||
uint32_t bufsize;
|
||||
int ret;
|
||||
struct ap_buffer_s *pBuf;
|
||||
|
||||
return NULL;
|
||||
DEBUGASSERT(bufdesc->u.ppBuffer != NULL);
|
||||
|
||||
/* Perform a user mode allocation */
|
||||
|
||||
bufsize = sizeof(struct ap_buffer_s) + bufdesc->numbytes;
|
||||
pBuf = kumalloc(bufsize);
|
||||
*bufdesc->u.ppBuffer = pBuf;
|
||||
|
||||
/* Test if the allocation was successful or not */
|
||||
|
||||
if (*bufdesc->u.ppBuffer == NULL)
|
||||
ret = -ENOMEM;
|
||||
else
|
||||
{
|
||||
/* Populate the buffer contents */
|
||||
|
||||
memset(pBuf, bufsize, 0);
|
||||
pBuf->i.channels = 1;
|
||||
pBuf->crefs = 1;
|
||||
pBuf->nmaxbytes = bufdesc->numbytes;
|
||||
pBuf->nbytes = 0;
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
pBuf->session = bufdesc->session;
|
||||
#endif
|
||||
sem_init(&pBuf->sem, 0, 1);
|
||||
ret = sizeof(struct audio_buf_desc_s);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -143,8 +173,19 @@ void apb_prepare(FAR struct ap_buffer_s *apb, int8_t allocmode, uint8_t format,
|
||||
|
||||
void apb_free(FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
int refcount;
|
||||
|
||||
/* Perform a reference count decrement and possibly release the memory */
|
||||
|
||||
apb_semtake(apb);
|
||||
refcount = apb->crefs--;
|
||||
apb_semgive(apb);
|
||||
|
||||
if (refcount == 1)
|
||||
{
|
||||
auddbg("Freeing %p\n", apb);
|
||||
kufree(apb);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -158,7 +199,11 @@ void apb_free(FAR struct ap_buffer_s *apb)
|
||||
|
||||
void apb_reference(FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
/* TODO: Implement the reference logic */
|
||||
/* Do we need any thread protection here? Almost certaily... */
|
||||
|
||||
apb_semtake(apb);
|
||||
apb->crefs++;
|
||||
apb_semgive(apb);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_AUDIO */
|
||||
|
@ -36,10 +36,10 @@
|
||||
#ifndef __INCLUDE_NUTTX_AUDIO_AUDIO_H
|
||||
#define __INCLUDE_NUTTX_AUDIO_AUDIO_H
|
||||
|
||||
/* For the purposes of this driver, an Audio device is any device that
|
||||
/* For the purposes of this driver, an Audio device is any device that
|
||||
* generates, records, mixes, or otherwise modifies audio data in any format,
|
||||
* such as PCM, MP3, AAC, etc.
|
||||
*
|
||||
*
|
||||
* The Audio driver is split into two parts:
|
||||
*
|
||||
* 1) An "upper half", generic driver that provides the comman Audio interface
|
||||
@ -57,6 +57,8 @@
|
||||
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/spi/spi.h>
|
||||
#include <queue.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#ifdef CONFIG_AUDIO
|
||||
|
||||
@ -69,10 +71,10 @@
|
||||
* CONFIG_DEBUG_VERBOSE), this will generate output that can be used to
|
||||
* debug Audio drivers.
|
||||
*/
|
||||
|
||||
|
||||
/* IOCTL Commands ***********************************************************/
|
||||
/* The Audio module uses a standard character driver framework. However, a
|
||||
* lot of the Audio driver functionality is configured via a device control
|
||||
* lot of the Audio driver functionality is configured via a device control
|
||||
* interface, such as sampling rate, volume, data format, etc.
|
||||
* The Audio ioctl commands are lised below:
|
||||
*
|
||||
@ -81,7 +83,7 @@
|
||||
* ioctl argument: Pointer to the audio_caps_s structure to receive the
|
||||
* capabilities info. The "len" and "type" fields should
|
||||
* be filled in prior to calling this ioctl. To get
|
||||
* overall capabilities, specify the type as
|
||||
* overall capabilities, specify the type as
|
||||
* AUDIO_TYPE_QUERY, otherwise specify any type that was
|
||||
* reported by the device during the QUERY.
|
||||
*
|
||||
@ -104,10 +106,21 @@
|
||||
*/
|
||||
|
||||
#define AUDIOIOC_GETCAPS _AUDIOIOC(1)
|
||||
#define AUDIOIOC_CONFIGURE _AUDIOIOC(2)
|
||||
#define AUDIOIOC_SHUTDOWN _AUDIOIOC(3)
|
||||
#define AUDIOIOC_START _AUDIOIOC(4)
|
||||
#define AUDIOIOC_STOP _AUDIOIOC(5)
|
||||
#define AUDIOIOC_RESERVE _AUDIOIOC(2)
|
||||
#define AUDIOIOC_RELEASE _AUDIOIOC(3)
|
||||
#define AUDIOIOC_CONFIGURE _AUDIOIOC(4)
|
||||
#define AUDIOIOC_SHUTDOWN _AUDIOIOC(5)
|
||||
#define AUDIOIOC_START _AUDIOIOC(6)
|
||||
#define AUDIOIOC_STOP _AUDIOIOC(7)
|
||||
#define AUDIOIOC_PAUSE _AUDIOIOC(8)
|
||||
#define AUDIOIOC_RESUME _AUDIOIOC(9)
|
||||
#define AUDIOIOC_GETBUFFERINFO _AUDIOIOC(10)
|
||||
#define AUDIOIOC_ALLOCBUFFER _AUDIOIOC(11)
|
||||
#define AUDIOIOC_FREEBUFFER _AUDIOIOC(12)
|
||||
#define AUDIOIOC_ENQUEUEBUFFER _AUDIOIOC(13)
|
||||
#define AUDIOIOC_REGISTERMQ _AUDIOIOC(14)
|
||||
#define AUDIOIOC_UNREGISTERMQ _AUDIOIOC(15)
|
||||
#define AUDIOIOC_HWRESET _AUDIOIOC(16)
|
||||
|
||||
/* Audio Device Types *******************************************************/
|
||||
/* The NuttX audio interface support different types of audio devices for
|
||||
@ -129,16 +142,17 @@
|
||||
/* Audio Format Types *******************************************************/
|
||||
/* The following defines the audio data format types in NuttX. */
|
||||
|
||||
#define AUDIO_FMT_UNDEF 0x00
|
||||
#define AUDIO_FMT_OTHER 0x01
|
||||
#define AUDIO_FMT_MPEG 0x02
|
||||
#define AUDIO_FMT_AC3 0x03
|
||||
#define AUDIO_FMT_WMA 0x04
|
||||
#define AUDIO_FMT_DTS 0x05
|
||||
#define AUDIO_FMT_PCM 0x06
|
||||
#define AUDIO_FMT_MP3 0x07
|
||||
#define AUDIO_FMT_MIDI 0x08
|
||||
#define AUDIO_FMT_OGG_VORBIS 0x09
|
||||
#define AUDIO_FMT_UNDEF 0x000
|
||||
#define AUDIO_FMT_OTHER 0x001
|
||||
#define AUDIO_FMT_MPEG 0x002
|
||||
#define AUDIO_FMT_AC3 0x004
|
||||
#define AUDIO_FMT_WMA 0x008
|
||||
#define AUDIO_FMT_DTS 0x010
|
||||
#define AUDIO_FMT_PCM 0x020
|
||||
#define AUDIO_FMT_WAV 0x020
|
||||
#define AUDIO_FMT_MP3 0x040
|
||||
#define AUDIO_FMT_MIDI 0x080
|
||||
#define AUDIO_FMT_OGG_VORBIS 0x100
|
||||
|
||||
/* Audio Sub-Format Types ***************************************************/
|
||||
|
||||
@ -156,21 +170,72 @@
|
||||
|
||||
/* Supported Sampling Rates *************************************************/
|
||||
|
||||
#define AUDIO_RATE_22K 0x01
|
||||
#define AUDIO_RATE_44K 0x02
|
||||
#define AUDIO_RATE_48K 0x03
|
||||
#define AUDIO_RATE_96K 0x04
|
||||
#define AUDIO_RATE_128K 0x05
|
||||
#define AUDIO_RATE_160K 0x06
|
||||
#define AUDIO_RATE_172K 0x07
|
||||
#define AUDIO_RATE_192K 0x08
|
||||
#define AUDIO_RATE_320K 0x09
|
||||
#define AUDIO_SAMP_RATE_8K 0x0001
|
||||
#define AUDIO_SAMP_RATE_11K 0x0002
|
||||
#define AUDIO_SAMP_RATE_16K 0x0004
|
||||
#define AUDIO_SAMP_RATE_22K 0x0008
|
||||
#define AUDIO_SAMP_RATE_32K 0x0010
|
||||
#define AUDIO_SAMP_RATE_44K 0x0020
|
||||
#define AUDIO_SAMP_RATE_48K 0x0040
|
||||
#define AUDIO_SAMP_RATE_96K 0x0080
|
||||
#define AUDIO_SAMP_RATE_128K 0x0100
|
||||
#define AUDIO_SAMP_RATE_160K 0x0200
|
||||
#define AUDIO_SAMP_RATE_172K 0x0400
|
||||
#define AUDIO_SAMP_RATE_192K 0x0800
|
||||
|
||||
/* Supported Bit Rates *************************************************/
|
||||
|
||||
#define AUDIO_BIT_RATE_22K 0x01
|
||||
#define AUDIO_BIT_RATE_44K 0x02
|
||||
#define AUDIO_BIT_RATE_48K 0x04
|
||||
#define AUDIO_BIT_RATE_96K 0x08
|
||||
#define AUDIO_BIT_RATE_128K 0x10
|
||||
#define AUDIO_BIT_RATE_160K 0x20
|
||||
#define AUDIO_BIT_RATE_172K 0x40
|
||||
#define AUDIO_BIT_RATE_192K 0x80
|
||||
|
||||
/* Supported Feature Units controls *****************************************/
|
||||
|
||||
#define AUDIO_FU_UNDEF 0x0000
|
||||
#define AUDIO_FU_MUTE 0x0001
|
||||
#define AUDIO_FU_VOLUME 0x0002
|
||||
#define AUDIO_FU_BASS 0x0004
|
||||
#define AUDIO_FU_MID 0x0008
|
||||
#define AUDIO_FU_TREBLE 0x0010
|
||||
#define AUDIO_FU_EQUALIZER 0x0020
|
||||
#define AUDIO_FU_AGC 0x0040
|
||||
#define AUDIO_FU_DELAY 0x0080
|
||||
#define AUDIO_FU_BASS_BOOST 0x0100
|
||||
#define AUDIO_FU_LOUDNESS 0x0200
|
||||
#define AUDIO_FU_INP_GAIN 0x0400
|
||||
#define AUDIO_FU_BALANCE 0x0800
|
||||
#define AUDIO_FU_PHASE_INVERT 0x1000
|
||||
#define AUDIO_FU_UNDERFLOW 0x2000
|
||||
#define AUDIO_FU_OVERFLOW 0x4000
|
||||
#define AUDIO_FU_LATENCY 0x8000
|
||||
|
||||
/* Processing Unit controls *************************************************/
|
||||
|
||||
#define AUDIO_PU_UNDEF 0x00
|
||||
#define AUDIO_PU_UPDOWNMIX 0x01
|
||||
#define AUDIO_PU_DOLBY_PROLOGIC 0x02
|
||||
#define AUDIO_PU_STEREO_EXTENDER 0x03
|
||||
|
||||
/* Stereo Extender PU Controls **********************************************/
|
||||
|
||||
#define AUDIO_STEXT_UNDEF 0x00
|
||||
#define AUDIO_STEXT_ENABLE 0x01
|
||||
#define AUDIO_STEXT_WIDTH 0x02
|
||||
#define AUDIO_STEXT_UNDERFLOW 0x03
|
||||
#define AUDIO_STEXT_OVERFLOW 0x04
|
||||
#define AUDIO_STEXT_LATENCY 0x05
|
||||
|
||||
/* Audio Callback Reasons ***************************************************/
|
||||
|
||||
#define AUDIO_CALLBACK_UNDEF 0x00
|
||||
#define AUDIO_CALLBACK_DEQUEUE 0x01
|
||||
#define AUDIO_CALLBACK_IOERR 0x02
|
||||
#define AUDIO_CALLBACK_COMPLETE 0x03
|
||||
|
||||
/* Audio Pipeline Buffer (AP Buffer) flags **********************************/
|
||||
|
||||
@ -186,6 +251,25 @@
|
||||
* operation, etc.
|
||||
*/
|
||||
|
||||
/* Standard Audio Message Queue message IDs */
|
||||
|
||||
#define AUDIO_MSG_NONE 0
|
||||
#define AUDIO_MSG_DEQUEUE 1
|
||||
#define AUDIO_MSG_START 2
|
||||
#define AUDIO_MSG_STOP 3
|
||||
#define AUDIO_MSG_PAUSE 4
|
||||
#define AUDIO_MSG_RESUME 5
|
||||
#define AUDIO_MSG_DATA_REQUEST 6
|
||||
#define AUDIO_MSG_ENQUEUE 7
|
||||
#define AUDIO_MSG_COMPLETE 8
|
||||
#define AUDIO_MSG_USER 64
|
||||
|
||||
/* Audio Pipeline Buffer flags */
|
||||
|
||||
#define AUDIO_APB_OUTPUT_ENQUEUED 0x0001;
|
||||
#define AUDIO_APB_OUTPUT_PROCESS 0x0002;
|
||||
#define AUDIO_APB_DEQUEUED 0x0004;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@ -212,6 +296,14 @@ struct audio_caps_s
|
||||
* by this lower-half driver. */
|
||||
};
|
||||
|
||||
struct audio_caps_desc_s
|
||||
{
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
FAR void *session; /* Associated session */
|
||||
#endif
|
||||
struct audio_caps_s caps; /* The capabilities struct */
|
||||
};
|
||||
|
||||
/* This structure describes the characteristics of the Audio samples */
|
||||
|
||||
struct audio_info_s
|
||||
@ -222,21 +314,99 @@ struct audio_info_s
|
||||
uint8_t subformat; /* Audio subformat (maybe should be combined with format? */
|
||||
};
|
||||
|
||||
/* This structure describes the preferred number and size of
|
||||
* audio pipeline buffers for the audio device. Each device
|
||||
* may have unique needs regarding size and qty of buffers,
|
||||
* so this info is queried from the lower-half driver.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS
|
||||
struct ap_buffer_info_s
|
||||
{
|
||||
apb_samp_t nbuffers; /* Preferred qty of buffers */
|
||||
apb_samp_t buffer_size; /* Preferred size of the buffers */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* This structure describes an Audio Pipeline Buffer */
|
||||
|
||||
struct ap_buffer_s
|
||||
{
|
||||
struct dq_entry_s dq_entry; /* Double linked queue entry */
|
||||
struct audio_info_s i; /* The info for samples in this buffer */
|
||||
apb_samp_t nmaxsamples;/* The maximum number of samples */
|
||||
apb_samp_t nsamples; /* The number of samples used */
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
FAR void *session; /* Associated session */
|
||||
#endif
|
||||
apb_samp_t nmaxbytes; /* The maximum number of bytes */
|
||||
apb_samp_t nbytes; /* The number of bytes used */
|
||||
apb_samp_t curbyte; /* Next byte to be processed */
|
||||
sem_t sem; /* Reference locking semaphore */
|
||||
uint16_t flags; /* Buffer flags */
|
||||
uint16_t crefs; /* Number of reference counts */
|
||||
uint8_t samp[0]; /* Offset of the first sample */
|
||||
} packed_struct;
|
||||
|
||||
/* Structure defining the messages passed to a listening audio thread
|
||||
* for dequeuing buffers and other operations. Also used to allocate
|
||||
* and enqueue buffers via the AUDIOIOC_ALLOCBUFFER, AUDIOIOC_FREEBUFFER,
|
||||
* and AUDIOIOC_ENQUEUEBUFFER ioctls.
|
||||
*/
|
||||
|
||||
struct audio_msg_s
|
||||
{
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
FAR void *session; /* Associated channel */
|
||||
#endif
|
||||
uint16_t msgId; /* Message ID */
|
||||
union
|
||||
{
|
||||
FAR void * pPtr; /* Buffer being dequeued */
|
||||
uint32_t data; /* Message data */
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
/* Strucure defining the built-in sounds */
|
||||
|
||||
#ifdef CONFIG_AUDIO_BUILTIN_SOUNDS
|
||||
struct audio_sound_s
|
||||
{
|
||||
const char *name; /* Name of the sound */
|
||||
uint32_t id; /* ID of the sound */
|
||||
uint32_t type; /* Type of sound */
|
||||
uint32_t size; /* Number of bytes in the sound */
|
||||
const uint8_t *data; /* Pointer to the data */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* Structure for allocating, freeing and enqueuing audio pipeline
|
||||
* buffers via the AUDIOIOC_ALLOCBUFFER, AUDIOIOC_FREEBUFFER,
|
||||
* and AUDIOIOC_ENQUEUEBUFFER ioctls.
|
||||
*/
|
||||
|
||||
struct audio_buf_desc_s
|
||||
{
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
FAR void *session; /* Associated channel */
|
||||
#endif
|
||||
uint16_t numbytes; /* Number of bytes to allocate */
|
||||
union
|
||||
{
|
||||
FAR struct ap_buffer_s *pBuffer; /* Buffer to free / enqueue */
|
||||
FAR struct ap_buffer_s **ppBuffer; /* Pointer to receive alloced buffer */
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Typedef for lower-level to upper-level callback for buffer dequeuing */
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
typedef CODE void (*audio_callback_t)(FAR void *priv, uint16_t reason,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status, FAR void *session);
|
||||
#else
|
||||
typedef CODE void (*audio_callback_t)(FAR void *priv, uint16_t reason,
|
||||
FAR struct ap_buffer_s *apb, uint16_t status);
|
||||
#endif
|
||||
|
||||
/* This structure is a set a callback functions used to call from the upper-
|
||||
* half, generic Audo driver into lower-half, platform-specific logic that
|
||||
@ -249,25 +419,29 @@ struct audio_ops_s
|
||||
/* This method is called to retrieve the lower-half device capabilities.
|
||||
* It will be called with device type AUDIO_TYPE_QUERY to request the
|
||||
* overall capabilities, such as to determine the types of devices supported
|
||||
* audio formats supported, etc. Then it may be called once or more with
|
||||
* reported supported device types to determine the specific capabilities
|
||||
* audio formats supported, etc. Then it may be called once or more with
|
||||
* reported supported device types to determine the specific capabilities
|
||||
* of that device type (such as MP3 encoder, WMA encoder, PCM output, etc.).
|
||||
*/
|
||||
|
||||
CODE int (*getcaps)(FAR struct audio_lowerhalf_s *dev, int type,
|
||||
CODE int (*getcaps)(FAR struct audio_lowerhalf_s *dev, int type,
|
||||
FAR struct audio_caps_s *pCaps);
|
||||
|
||||
/* This method is called to bind the lower-level driver to the upper-level
|
||||
* driver and to configure the driver for a specific mode of
|
||||
* operation defined by the parameters selected in supplied device caps
|
||||
* structure. The lower-level device should perform any initialization
|
||||
* needed to prepare for operations in the specified mode. It should not,
|
||||
* structure. The lower-level device should perform any initialization
|
||||
* needed to prepare for operations in the specified mode. It should not,
|
||||
* however, process any audio data until the start method is called.
|
||||
*/
|
||||
|
||||
CODE int (*configure)(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR const struct audio_caps_s *pCaps,
|
||||
audio_callback_t upper, FAR void *priv);
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
CODE int (*configure)(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR void *session, FAR const struct audio_caps_s *pCaps);
|
||||
#else
|
||||
CODE int (*configure)(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR const struct audio_caps_s *pCaps);
|
||||
#endif
|
||||
|
||||
/* This method is called when the driver is closed. The lower half driver
|
||||
* should stop processing audio data, including terminating any active
|
||||
@ -280,26 +454,75 @@ struct audio_ops_s
|
||||
|
||||
CODE int (*shutdown)(FAR struct audio_lowerhalf_s *dev);
|
||||
|
||||
/* Start audio streaming in the configured mode. For input and synthesis
|
||||
* devices, this means it should begin sending streaming audio data. For output
|
||||
* or processing type device, it means it should begin processing of any enqueued
|
||||
/* Start audio streaming in the configured mode. For input and synthesis
|
||||
* devices, this means it should begin sending streaming audio data. For output
|
||||
* or processing type device, it means it should begin processing of any enqueued
|
||||
* Audio Pipline Buffers.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
CODE int (*start)(FAR struct audio_lowerhalf_s *dev, FAR void *session);
|
||||
#else
|
||||
CODE int (*start)(FAR struct audio_lowerhalf_s *dev);
|
||||
#endif
|
||||
|
||||
/* Stop audio streaming and/or processing of enqueued Audio Pipeline Buffers */
|
||||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
CODE int (*stop)(FAR struct audio_lowerhalf_s *dev, FAR void *session);
|
||||
#else
|
||||
CODE int (*stop)(FAR struct audio_lowerhalf_s *dev);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Enqueue a buffer for processing. This is a non-blocking enqueue operation.
|
||||
* If the lower-half driver's buffer queue is full, then it should return an
|
||||
j* error code of -ENOMEM, and the upper-half driver can decide to either block
|
||||
* the calling thread or deal with it in a non-blocking manner.
|
||||
|
||||
* For each call to enqueuebuffer, the lower-half driver must call
|
||||
* audio_dequeuebuffer when it is finished processing the bufferr, passing the
|
||||
* previously enqueued apb and a dequeue status so that the upper-half driver
|
||||
/* Pause the audio stream. Should keep current playback context active
|
||||
* in case a resume is issued. Could be called and then followed by a stop.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
CODE int (*pause)(FAR struct audio_lowerhalf_s *dev, FAR void *session);
|
||||
#else
|
||||
CODE int (*pause)(FAR struct audio_lowerhalf_s *dev);
|
||||
#endif
|
||||
|
||||
/* Resumes audio streaming after a pause */
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
CODE int (*resume)(FAR struct audio_lowerhalf_s *dev, FAR void *session);
|
||||
#else
|
||||
CODE int (*resume)(FAR struct audio_lowerhalf_s *dev);
|
||||
#endif
|
||||
#endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */
|
||||
|
||||
/* Allocate an audio pipeline buffer. This routine provides the
|
||||
* lower-half driver with the opportunity to perform special buffer
|
||||
* allocation if needed, such as allocating from a specific memory
|
||||
* region (DMA-able, etc.). If not supplied, then the top-half
|
||||
* driver will perform a standard kumalloc using normal user-space
|
||||
* memory region.
|
||||
*/
|
||||
|
||||
CODE int (*allocbuffer)(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR struct audio_buf_desc_s *apb);
|
||||
|
||||
/* Free an audio pipeline buffer. If the lower-level driver
|
||||
* provides an allocbuffer routine, it should also provide the
|
||||
* freebuffer routine to perform the free operation.
|
||||
*/
|
||||
|
||||
CODE int (*freebuffer)(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR struct audio_buf_desc_s *apb);
|
||||
|
||||
/* Enqueue a buffer for processing. This is a non-blocking enqueue operation.
|
||||
* If the lower-half driver's buffer queue is full, then it should return an
|
||||
* error code of -ENOMEM, and the upper-half driver can decide to either block
|
||||
* the calling thread or deal with it in a non-blocking manner.
|
||||
|
||||
* For each call to enqueuebuffer, the lower-half driver must call
|
||||
* audio_dequeuebuffer when it is finished processing the bufferr, passing the
|
||||
* previously enqueued apb and a dequeue status so that the upper-half driver
|
||||
* can decide if a waiting thread needs to be release, if the dequeued buffer
|
||||
* should be passed to the next block in the Audio Pipeline, etc.
|
||||
*/
|
||||
@ -316,6 +539,37 @@ struct audio_ops_s
|
||||
|
||||
CODE int (*ioctl)(FAR struct audio_lowerhalf_s *dev,
|
||||
int cmd, unsigned long arg);
|
||||
|
||||
/* Lower-half logic may support platform-specific read commands */
|
||||
|
||||
CODE int (*read)(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR char *buffer, size_t buflen);
|
||||
|
||||
/* Lower-half logic may support platform-specific write commands */
|
||||
|
||||
CODE int (*write)(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR const char *buffer, size_t buflen);
|
||||
|
||||
/* Reserve a session (may only be one per device or may be multiple) for
|
||||
* use by a client. Client software can open audio devices and issue
|
||||
* AUDIOIOC_GETCAPS calls freely, but other operations require a
|
||||
* reservation. A session reservation will assign a context that must
|
||||
* be passed with
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
CODE int (*reserve)(FAR struct audio_lowerhalf_s *dev, FAR void **psession );
|
||||
#else
|
||||
CODE int (*reserve)(FAR struct audio_lowerhalf_s *dev);
|
||||
#endif
|
||||
|
||||
/* Release a session. */
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
CODE int (*release)(FAR struct audio_lowerhalf_s *dev, FAR void *session );
|
||||
#else
|
||||
CODE int (*release)(FAR struct audio_lowerhalf_s *dev);
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This structure is the generic form of state structure used by lower half
|
||||
@ -325,8 +579,8 @@ struct audio_ops_s
|
||||
* maintain state information.
|
||||
*
|
||||
* Normally that Audio logic will have its own, custom state structure
|
||||
* that is simply cast to struct audio_lowerhalf_s. In order to perform such
|
||||
* casts, the initial fields of the custom state structure match the initial
|
||||
* that is simply cast to struct audio_lowerhalf_s. In order to perform such
|
||||
* casts, the initial fields of the custom state structure match the initial
|
||||
* fields of the following generic Audio state structure.
|
||||
*/
|
||||
|
||||
@ -348,7 +602,7 @@ struct audio_lowerhalf_s
|
||||
|
||||
FAR void *priv;
|
||||
|
||||
/* The custom Audio device state structure may include additional fields
|
||||
/* The custom Audio device state structure may include additional fields
|
||||
* after the pointer to the Audio callback structure.
|
||||
*/
|
||||
};
|
||||
@ -363,7 +617,8 @@ struct audio_lowerhalf_s
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
@ -387,7 +642,7 @@ extern "C" {
|
||||
* a full path to the driver in the format "/dev/audio/[name]" in the NuttX
|
||||
* filesystem (i.e. the path "/dev/audio" will be prepended to the supplied
|
||||
* device name. The recommended convention is to name Audio drivers
|
||||
* based on the type of functionality they provide, such as "/dev/audio/pcm0",
|
||||
* based on the type of functionality they provide, such as "/dev/audio/pcm0",
|
||||
* "/dev/audio/midi0", "/dev/audio/mp30, etc.
|
||||
* dev - A pointer to an instance of lower half audio driver. This instance
|
||||
* is bound to the Audio driver and must persists as long as the driver
|
||||
@ -398,7 +653,7 @@ extern "C" {
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev);
|
||||
int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: abp_alloc
|
||||
@ -410,13 +665,14 @@ EXTERN int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *de
|
||||
* and then call apb_prepare, passing it the allocated memory.
|
||||
*
|
||||
* Input parameters:
|
||||
* bufdesc: Pointer to a buffer descriptor
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to the allocated buffer or NULL if no memory.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct ap_buffer_s *apb_alloc(int type, int sampleCount);
|
||||
int apb_alloc(FAR struct audio_buf_desc_s *bufdesc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: abp_prepare
|
||||
@ -437,8 +693,8 @@ FAR struct ap_buffer_s *apb_alloc(int type, int sampleCount);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void apb_prepare(struct ap_buffer_s *apb, int8_t allocmode, uint8_t format,
|
||||
uint8_t subformat, apb_samp_t maxsamples);
|
||||
void apb_prepare(struct ap_buffer_s *apb, int8_t allocmode, uint8_t format,
|
||||
uint8_t subformat, apb_samp_t maxsamples);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: apb_free
|
||||
@ -447,7 +703,7 @@ EXTERN void apb_prepare(struct ap_buffer_s *apb, int8_t allocmode, uint8_t forma
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void apb_free(FAR struct ap_buffer_s *apb);
|
||||
void apb_free(FAR struct ap_buffer_s *apb);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: apb_reference
|
||||
@ -458,7 +714,7 @@ EXTERN void apb_free(FAR struct ap_buffer_s *apb);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void apb_reference(FAR struct ap_buffer_s *apb);
|
||||
void apb_reference(FAR struct ap_buffer_s *apb);
|
||||
|
||||
/****************************************************************************
|
||||
* Platform-Dependent "Lower-Half" Audio Driver Interfaces
|
||||
|
Loading…
Reference in New Issue
Block a user