From: bsvt Date: Mon, 3 Jul 2017 11:08:56 +0000 (-0700) Subject: Audio devices and audio pipeline buffer support X-Git-Tag: 1.1_Public_Release~188^2~48 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=30c4ec4adad890813f9578e2c9aabdbf1d3c6ef4;p=rtos%2Ftinyara.git Audio devices and audio pipeline buffer support --- diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index cfb394f..27009b1 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -691,3 +691,10 @@ config LIB_USRWORKSTACKSIZE endif # LIB_USRWORK endif # BUILD_PROTECTED || BUILD_KERNEL + + +config AUDIO + bool "Audio library" + default n + ---help--- + Audio library. diff --git a/lib/libc/audio/Make.defs b/lib/libc/audio/Make.defs index 4c35176..de3b7d5 100644 --- a/lib/libc/audio/Make.defs +++ b/lib/libc/audio/Make.defs @@ -1,4 +1,4 @@ -########################################################################### +############################################################################ # # Copyright 2017 Samsung Electronics All Rights Reserved. # @@ -14,7 +14,7 @@ # either express or implied. See the License for the specific # language governing permissions and limitations under the License. # -########################################################################### +############################################################################ ############################################################################ # libc/audio/Make.defs # @@ -53,7 +53,6 @@ ifeq ($(CONFIG_AUDIO),y) CSRCS += lib_buffer.c -# Add the audio/ directory to the build DEPPATH += --dep-path audio VPATH += :audio diff --git a/lib/libc/audio/lib_buffer.c b/lib/libc/audio/lib_buffer.c index f8fca68..6f8c768 100644 --- a/lib/libc/audio/lib_buffer.c +++ b/lib/libc/audio/lib_buffer.c @@ -67,10 +67,7 @@ #include #include - -#include "lib_internal.h" - -#if defined(CONFIG_AUDIO) +#include "libc.h" /**************************************************************************** * Pre-processor Definitions @@ -135,6 +132,7 @@ int apb_alloc(FAR struct audio_buf_desc_s *bufdesc) int ret; struct ap_buffer_s *apb; + DEBUGASSERT(bufdesc != NULL); DEBUGASSERT(bufdesc->u.ppBuffer != NULL); /* Perform a user mode allocation */ @@ -185,7 +183,7 @@ void apb_free(FAR struct ap_buffer_s *apb) apb_semgive(apb); if (refcount <= 1) { - audvdbg("Freeing %p\n", apb); + audinfo("Freeing %p\n", apb); lib_ufree(apb); } } @@ -208,4 +206,3 @@ void apb_reference(FAR struct ap_buffer_s *apb) apb_semgive(apb); } -#endif /* CONFIG_AUDIO */ diff --git a/lib/libc/libc.h b/lib/libc/libc.h new file mode 100644 index 0000000..1a210ab --- /dev/null +++ b/lib/libc/libc.h @@ -0,0 +1,143 @@ + +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed 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. + * + ****************************************************************************/ +/**************************************************************************** + * libc/libc.h + * + * Copyright (C) 2007-2014, 2016-2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __LIB_LIBC_H +#define __LIB_LIBC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The Tinyara C library an be build in two modes: (1) as a standard, C-library + * that can be used by normal, user-space applications, or (2) as a special, + * kernel-mode C-library only used within the OS. If NuttX is not being + * built as separated kernel- and user-space modules, then only the first + * mode is supported. + */ + +#if (defined(CONFIG_BUILD_PROTECTED) && defined(__KERNEL__)) || \ + defined(CONFIG_BUILD_KERNEL) +#include + +/* Domain-specific allocations */ + +#define lib_malloc(s) kmm_malloc(s) +#define lib_zalloc(s) kmm_zalloc(s) +#define lib_realloc(p,s) kmm_realloc(p,s) +#define lib_memalign(p,s) kmm_memalign(p,s) +#define lib_free(p) kmm_free(p) + +/* User-accessible allocations */ + +#define lib_umalloc(s) kumm_malloc(s) +#define lib_uzalloc(s) kumm_zalloc(s) +#define lib_urealloc(p,s) kumm_realloc(p,s) +#define lib_ufree(p) kumm_free(p) + +#else +#include + +/* Domain-specific allocations */ + +#define lib_malloc(s) malloc(s) +#define lib_zalloc(s) zalloc(s) +#define lib_realloc(p,s) realloc(p,s) +#define lib_free(p) free(p) + +/* User-accessible allocations */ + +#define lib_umalloc(s) malloc(s) +#define lib_uzalloc(s) zalloc(s) +#define lib_urealloc(p,s) realloc(p,s) +#define lib_ufree(p) free(p) + +#endif + +#define LIB_BUFLEN_UNKNOWN INT_MAX + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __LIB_LIBC_H */ diff --git a/os/drivers/Kconfig b/os/drivers/Kconfig index dd2a24e..d2bfb25 100644 --- a/os/drivers/Kconfig +++ b/os/drivers/Kconfig @@ -185,32 +185,6 @@ config GPIO driver. See include/tinyara/gpio.h for further GPIO driver information. -menuconfig I2S - bool "I2S Driver Support" - default n - ---help--- - This selection enables selection of common I2S options. This option - should be enabled by all platforms that support I2S interfaces. - See include/tinyara/audio/i2s.h for further I2S driver information. - -if I2S -endif # I2S - -menuconfig AUDIO_DEVICES - bool "Audio Device Support" - default n - ---help--- - Enable support for audio device drivers. This includes drivers for - MP3, WMA and Ogg Vorbis encoding, decoding, as well as drivers for - interfacing with external DSP chips to perform custom audio functions. - - NOTE: All of these drivers depend on support from the audio subsystem - enabled with the AUDIO selection. - -if AUDIO_DEVICES -source drivers/audio/Kconfig -endif # AUDIO_DEVICES - menuconfig BCH bool "Block-to-Character (BCH) Support" default n @@ -344,17 +318,6 @@ config TIMER driver. See include/tinyara/timer.h for further timer driver information. -menuconfig I2S - bool "I2S Driver Support" - default n - ---help--- - This selection enables selection of common I2S options. This option - should be enabled by all platforms that support I2S interfaces. - See include/tinyara/audio/i2s.h for further I2S driver information. - -if I2S -endif # I2S - menuconfig ANALOG bool "Analog Device(ADC/DAC) Support" default n @@ -368,22 +331,6 @@ if ANALOG source drivers/analog/Kconfig endif # ANALOG -menuconfig AUDIO_DEVICES - bool "Audio Device Support" - default n - ---help--- - Enable support for audio device drivers. This includes drivers for - MP3, WMA and Ogg Vorbis encoding, decoding, as well as drivers for - interfacing with external DSP chips to perform custom audio functions. - - NOTE: All of these drivers depend on support from the audio subsystem - enabled with the AUDIO selection. - -if AUDIO_DEVICES -source drivers/audio/Kconfig -endif # AUDIO_DEVICES - - menuconfig LCD bool "LCD Driver Support" default n @@ -462,6 +409,17 @@ if SERIAL source drivers/serial/Kconfig endif # SERIAL +menuconfig SENSOR + bool "Sensor Driver Support" + default n + ---help--- + This selection enables building of the sensor driver. + +if SENSOR +source drivers/sensors/Kconfig +endif # SENSOR + + menuconfig USBDEV bool "USB Device Driver Support" default n @@ -491,12 +449,4 @@ menuconfig DRIVERS_WIRELESS source drivers/wireless/Kconfig -menuconfig SENSOR - bool "Sensor Driver Support" - default n - ---help--- - This selection enables building of the sensor driver. - -if SENSOR -source drivers/sensors/Kconfig -endif +source drivers/audio/Kconfig diff --git a/os/drivers/audio/Kconfig b/os/drivers/audio/Kconfig index 65f3c42..35392fe 100644 --- a/os/drivers/audio/Kconfig +++ b/os/drivers/audio/Kconfig @@ -3,6 +3,16 @@ # see kconfig-language at https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt # +menuconfig I2S + bool "I2S Driver Support" + default n + ---help--- + This selection enables selection of common I2S options. This option + should be enabled by all platforms that support I2S interfaces. + See include/tinyara/audio/i2s.h for further I2S driver information. + +if I2S + config AUDIO_I2SCHAR bool "I2S character driver (for testing only)" default n @@ -34,110 +44,145 @@ config AUDIO_I2SCHAR_TXTIMEOUT The special value of zero disables RX timeouts. Default: 0 endif # AUDIO_I2SCHAR +endif # I2S -config AUDIO_NULL - bool "NULL audio device" +config AUDIO_DEVICES + bool "Support for Audio Devices" default n depends on AUDIO ---help--- - A do-nothinig audio device driver to simplify testing of audio - decoders. + Enables support for Audio Devices. -config AUDIO_ALC5658 - bool "ALC5658 audio chip" - depends on AUDIO +if AUDIO_DEVICES + +config AUDIO_MULTI_SESSION + bool "Support multiple sessions" + default n ---help--- - Select to enable support for the ALC5658 Audio codec by Realtek - NOTE: This driver also depends on both I2C and I2S support although - that dependency is not explicit here. + 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. -if AUDIO_ALC5658 +menu "Audio Buffer Configuration" -config ALC5658_INITVOLUME - int "ALC5658 initial volume setting" - default 250 +config AUDIO_LARGE_BUFFERS + bool "Support Audio Buffers with greater than 65K samples" + default n + ---help--- + 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 ALC5658_INFLIGHT - int "ALC5658 maximum in-flight audio buffers" +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 ALC5658_MSG_PRIO - int "ALC5658 message priority" - default 1 - -config ALC5658_BUFFER_SIZE - int "ALC5658 preferred buffer size" +config AUDIO_BUFFER_NUMBYTES + int "Size of each audio buffer for audio processing" default 8192 - -config ALC5658_NUM_BUFFERS - int "ALC5658 preferred number of buffers" - default 4 - -config ALC5658_WORKER_STACKSIZE - int "ALC5658 worker thread stack size" - default 768 - -config ALC5658_REGDUMP - bool "ALC5658 register dump" - default n ---help--- - Enable logic to dump the contents of all ALC5658 registers. + 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 ALC5658_CLKDEBUG - bool "ALC5658 clock analysis" +config AUDIO_DRIVER_SPECIFIC_BUFFERS + bool "Support for Driver specified buffer sizes" default n ---help--- - Enable logic to analyze ALC5658 clock configuation. + 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. -endif # AUDIO_ALC5658 +endmenu # Audio Buffer Configuration -config AUDIO_ALC5658CHAR - bool "ALC5658 Character Driver (for testing and demo only)" - depends on I2S && AUDIO && I2C && !AUDIO_ALC5658 +menu "Supported Audio Formats" + +config AUDIO_FORMAT_PCM + bool "PCM Audio" + default y ---help--- - This selection enables a simple character driver that supports ALC codec - transfers via a read() and write() ioctl. The intent of this driver is to - support ALC codec operation. It is not an audio driver but does conform to - some of the buffer management heuristics of an audio driver. It can be used - as real driver application with come restrictions. - form. + Build in support for PCM Audio format. -if AUDIO_ALC5658CHAR +endmenu -config AUDIO_ALC5658CHAR_RXTIMEOUT - int "RX timeout" - default 0 - ---help--- - This is a fixed timeout value that will be used for all receiver - transfers. This is in units of system clock ticks (configurable). - The special value of zero disables RX timeouts. Default: 0 +menu "Exclude Specific Audio Features" -config AUDIO_ALC5658CHAR_TXTIMEOUT - int "TX timeout" - default 0 +config AUDIO_EXCLUDE_PAUSE_RESUME + bool "Exclude pause and resume controls" + default n ---help--- - This is a fixed timeout value that will be used for all transmitter - transfers. This is in units of system clock ticks (configurable). - The special value of zero disables RX timeouts. Default: 0 + 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 sytem + notification or error type sounds that typically only last a second + or two, then there is no need (or chance) to stop the sound + playback once it has started. + +config AUDIO_EXCLUDE_FFORWARD + bool "Exclude fast forward controls" + default n if !AUDIO_EXCLUDE_STOP + default y if AUDIO_EXCLUDE_STOP + ---help--- + Exclude building support for fast forwarding through audio files + once they are submitted. Selecting this option would only make + if the underlying audio decoding logic is capable of sub-sampling + in the stream of audio data. + +config AUDIO_EXCLUDE_REWIND + bool "Exclude rewind controls" + default y + ---help--- + Rewind may be supported by some audio devices, but not the typical + device that receives a non-seekable, stream of audio buffers. -endif # AUDIO_ALC5658CHAR +endmenu + +config AUDIO_CUSTOM_DEV_PATH + bool "Use custom device path" + default n + ---help--- + By default, all audio devices on the target are are registered in the + /dev/audio directory. Select this option to change the default location + for the device registration. -if AUDIO_NULL +if AUDIO_CUSTOM_DEV_PATH -config AUDIO_NULL_MSG_PRIO - int "Null audio device message priority" - default 1 +config AUDIO_DEV_ROOT + bool "Place audio devices in /dev" + default n + ---help--- + This option causes all device entries to appear in /dev with all the + other device entries. This option generates the smallest code and + RAM footprint. -config AUDIO_NULL_BUFFER_SIZE - int "Null audio device preferred buffer size" - default 8192 +if !AUDIO_DEV_ROOT -config AUDIO_NULL_NUM_BUFFERS - int "Null audio device preferred number of buffers" - default 4 +config AUDIO_DEV_PATH + string "Base path for Audio devices" + default "/dev/audio" + ---help--- + The path on the target where audio devices are registered. The default + is to place all audio devices in the /dev/audio/ directory. -config AUDIO_NULL_WORKER_STACKSIZE - int "Null audio device worker thread stack size" - default 768 +endif # AUDIO_CUSTOM_DEV_PATH +endif #AUDIO_DEV_ROOT -endif # AUDIO_NULL +endif # AUDIO_DEVICES diff --git a/os/drivers/audio/Make.defs b/os/drivers/audio/Make.defs index 82fefb9..3789ace 100644 --- a/os/drivers/audio/Make.defs +++ b/os/drivers/audio/Make.defs @@ -55,11 +55,7 @@ # Include Audio drivers ifeq ($(CONFIG_AUDIO_DEVICES),y) - -ifeq ($(CONFIG_AUDIO_NULL),y) -CSRCS += audio_null.c -endif - +CSRCS += audio.c ifeq ($(CONFIG_AUDIO_I2SCHAR),y) CSRCS += i2schar.c endif diff --git a/os/drivers/audio/audio.c b/os/drivers/audio/audio.c new file mode 100644 index 0000000..e7ee19f --- /dev/null +++ b/os/drivers/audio/audio.c @@ -0,0 +1,953 @@ + +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed 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. + * + ****************************************************************************/ +/**************************************************************************** + * audio/audio.c + * + * Copyright (C) 2013 Ken Pettit. All rights reserved. + * Author: Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_AUDIO + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing Audio */ + +#ifndef AUDIO_MAX_DEVICE_PATH +#define AUDIO_MAX_DEVICE_PATH 32 +#endif + +#ifndef CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO +#define CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO 1 +#endif + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/* This structure describes the state of the upper half driver */ + +struct audio_upperhalf_s { + uint8_t crefs; /* The number of times the device has been opened */ + volatile bool started; /* True: playback is active */ + sem_t exclsem; /* Supports mutual exclusion */ + FAR struct audio_lowerhalf_s *dev; /* lower-half state */ + mqd_t usermq; /* User mode app's message queue */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +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_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 + ****************************************************************************/ + +static const struct file_operations g_audioops = { + audio_open, /* open */ + audio_close, /* close */ + audio_read, /* read */ + audio_write, /* write */ + 0, /* seek */ + audio_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: audio_open + * + * Description: + * This function is called whenever the Audio device is opened. + * + ************************************************************************************/ + +static int audio_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct audio_upperhalf_s *upper = inode->i_private; + uint8_t tmp; + int ret; + + audinfo("crefs: %d\n", upper->crefs); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) { + ret = -errno; + goto errout; + } + + /* Increment the count of references to the device. If this the first + * time that the driver has been opened for this device, then initialize + * the device. + */ + + tmp = upper->crefs + 1; + if (tmp == 0) { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* Save the new open count on success */ + + upper->crefs = tmp; + upper->usermq = NULL; + ret = OK; + +errout_with_sem: + sem_post(&upper->exclsem); + +errout: + return ret; +} + +/************************************************************************************ + * Name: audio_close + * + * Description: + * This function is called when the Audio device is closed. + * + ************************************************************************************/ + +static int audio_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct audio_upperhalf_s *upper = inode->i_private; + int ret; + + audinfo("crefs: %d\n", upper->crefs); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) { + ret = -errno; + goto errout; + } + + /* Decrement the references to the driver. If the reference count will + * decrement to 0, then uninitialize the driver. + */ + + if (upper->crefs > 1) { + upper->crefs--; + } else { + FAR struct audio_lowerhalf_s *lower = upper->dev; + + /* There are no more references to the port */ + + upper->crefs = 0; + + /* Disable the Audio device */ + + DEBUGASSERT(lower->ops->shutdown != NULL); + audinfo("calling shutdown: %d\n"); + + lower->ops->shutdown(lower); + } + ret = OK; + +//errout_with_sem: + sem_post(&upper->exclsem); + +errout: + return ret; +} + +/************************************************************************************ + * Name: audio_read + * + * Description: + * A dummy read method. This is provided only to satsify the VFS layer. + * + ************************************************************************************/ + +static ssize_t audio_read(FAR struct file *filep, FAR 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 read operations get passed directly to the lower-level */ + + if (lower->ops->read != NULL) { + return lower->ops->read(lower, buffer, buflen); + } + + return 0; +} + +/************************************************************************************ + * Name: audio_write + * + * Description: + * A dummy write method. This is provided only to satsify the VFS layer. + * + ************************************************************************************/ + +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; +} + +/************************************************************************************ + * Name: audio_start + * + * Description: + * Handle the AUDIOIOC_START ioctl command + * + ************************************************************************************/ + +#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; + + DEBUGASSERT(upper != NULL && lower->ops->start != NULL); + + /* Verify that the Audio is not already running */ + + if (!upper->started) { + /* 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 audio stream was started + * successfully. + */ + + if (ret == OK) { + /* Indicate that the audio stream has started */ + + upper->started = true; + } + } + + return ret; +} + +/************************************************************************************ + * Name: audio_ioctl + * + * Description: + * The standard ioctl method. This is where ALL of the Audio work is done. + * + ************************************************************************************/ + +static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct audio_upperhalf_s *upper = inode->i_private; + FAR struct audio_lowerhalf_s *lower = upper->dev; + FAR struct audio_buf_desc_s *bufdesc; +#ifdef CONFIG_AUDIO_MULTI_SESSION + FAR void *session; +#endif + int ret; + + audinfo("cmd: %d arg: %ld\n", cmd, arg); + + /* Get exclusive access to the device structures */ + + ret = sem_wait(&upper->exclsem); + if (ret < 0) { + return ret; + } + + /* Handle built-in ioctl commands */ + + switch (cmd) { + /* AUDIOIOC_GETCAPS - Get the audio device capabilities. + * + * ioctl argument: A pointer to the audio_caps_s structure. + */ + + case AUDIOIOC_GETCAPS: { + FAR struct audio_caps_s *caps = (FAR struct audio_caps_s *)((uintptr_t) arg); + DEBUGASSERT(lower->ops->getcaps != NULL); + + audinfo("AUDIOIOC_GETCAPS: Device=%d\n", caps->ac_type); + + /* Call the lower-half driver capabilities handler */ + + ret = lower->ops->getcaps(lower, caps->ac_type, caps); + } + break; + + case AUDIOIOC_CONFIGURE: { + FAR const struct audio_caps_desc_s *caps = (FAR const struct audio_caps_desc_s *)((uintptr_t) arg); + DEBUGASSERT(lower->ops->configure != NULL); + + audinfo("AUDIOIOC_INITIALIZE: Device=%d\n", caps->caps.ac_type); + + /* Call the lower-half driver configure handler */ + +#ifdef CONFIG_AUDIO_MULTI_SESSION + ret = lower->ops->configure(lower, caps->session, &caps->caps); +#else + ret = lower->ops->configure(lower, &caps->caps); +#endif + } + break; + + case AUDIOIOC_SHUTDOWN: { + DEBUGASSERT(lower->ops->shutdown != NULL); + + audinfo("AUDIOIOC_SHUTDOWN\n"); + + /* Call the lower-half driver initialize handler */ + ret = lower->ops->shutdown(lower); + } + break; + + /* AUDIOIOC_START - Start the audio stream. The AUDIOIOC_SETCHARACTERISTICS + * command must have previously been sent. + * + * ioctl argument: Audio session + */ + + case AUDIOIOC_START: { + audinfo("AUDIOIOC_START\n"); + DEBUGASSERT(lower->ops->start != NULL); + + /* Start the audio stream */ + +#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 audio stream. + * + * ioctl argument: Audio session + */ + +#ifndef CONFIG_AUDIO_EXCLUDE_STOP + case AUDIOIOC_STOP: { + audinfo("AUDIOIOC_STOP\n"); + DEBUGASSERT(lower->ops->stop != NULL); + + 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: { + audinfo("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: { + audinfo("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: { + audinfo("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 kumm_malloc 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: { + audinfo("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 apb_free 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: { + audinfo("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: { + audinfo("AUDIOIOC_REGISTERMQ\n"); + + 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: { + audinfo("AUDIOIOC_UNREGISTERMQ\n"); + + 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: { + audinfo("AUDIOIOC_RESERVE\n"); + 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: { + audinfo("AUDIOIOC_RELEASE\n"); + 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 */ + + default: { + audinfo("Forwarding unrecognized cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(lower->ops->ioctl != NULL); + ret = lower->ops->ioctl(lower, cmd, arg); + } + break; + } + + sem_post(&upper->exclsem); + 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; + + audinfo("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, (FAR const char *)&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; + + audinfo("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, (FAR const char *)&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; + + audinfo("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: { + auderr("ERROR: Unknown callback reason code %d\n", reason); + break; + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: audio_register + * + * Description: + * This function binds an instance of a "lower half" audio driver with the + * "upper half" Audio device and registers that device so that can be used + * by application code. + * + * When this function is called, the "lower half" driver should be in the + * reset state (as if the shutdown() method had already been called). + * + * Input parameters: + * path - The full path to the driver to be registers in the tinyara pseudo- + * filesystem. The recommended convention is to name Audio drivers + * based on the function they provide, such as "/dev/pcm0", "/dev/mp31", + * 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 + * persists. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +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]; + static bool dev_audio_created = false; +#ifndef CONFIG_AUDIO_CUSTOM_DEV_PATH + FAR const char *devname = "/dev/audio"; +#elif !defined(CONFIG_AUDIO_DEV_ROOT) + FAR const char *devname = CONFIG_AUDIO_DEV_PATH; + FAR const char *ptr; + FAR char *pathptr; +#endif + + /* Allocate the upper-half data structure */ + + upper = (FAR struct audio_upperhalf_s *)kmm_zalloc(sizeof(struct audio_upperhalf_s)); + if (!upper) { + auderr("ERROR: Allocation failed\n"); + return -ENOMEM; + } + + /* Initialize the Audio device structure (it was already zeroed by kmm_zalloc()) */ + + sem_init(&upper->exclsem, 0, 1); + upper->dev = dev; + +#ifdef CONFIG_AUDIO_CUSTOM_DEV_PATH + +#ifdef CONFIG_AUDIO_DEV_ROOT + + /* This is the simple case ... No need to make a directory */ + + strcpy(path, "/dev/"); + strcat(path, name); + +#else + /* Ensure the path begins with "/dev" as we don't support placing device + * anywhere but in the /dev directory + */ + + DEBUGASSERT(strncmp(devname, "/dev", 4) == 0); + + /* Create a /dev/audio directory. */ + + if (!dev_audio_created) { + /* Get path name after "/dev" */ + + ptr = &devname[4]; + if (*ptr == '/') { + ptr++; + } + + strcpy(path, "/dev/"); + pathptr = &path[5]; + + /* Do mkdir for each segment of the path */ + + while (*ptr != '\0') { + /* Build next path segment into path variable */ + + while (*ptr != '/' && *ptr != '\0') { + *pathptr++ = *ptr++; + } + *pathptr = '\0'; + + /* Make this level of directory */ + + mkdir(path, 0644); + + /* Check for another level */ + + *pathptr++ = '/'; + if (*ptr == '/') { + ptr++; + } + } + + /* Indicate we have created the audio dev path */ + + dev_audio_created = true; + } + + /* Now build the path for registration */ + + strcpy(path, devname); + if (devname[sizeof(devname) - 1] != '/') { + strcat(path, "/"); + } + + strcat(path, name); + +#endif /* CONFIG_AUDIO_DEV_PATH=="/dev" */ + +#else /* CONFIG_AUDIO_CUSTOM_DEV_PATH */ + + /* Create a /dev/audio directory. */ + + if (!dev_audio_created) { + /* We don't check for error here because even if it fails, then + * the register_driver call below will return an error condition + * for us. + */ + + mkdir(devname, 0644); + dev_audio_created = true; + } + + /* Register the Audio device */ + + memset(path, 0, AUDIO_MAX_DEVICE_PATH); + strcpy(path, devname); + strcat(path, "/"); + 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; + + audinfo("Registering %s\n", path); + return register_driver(path, &g_audioops, 0666, upper); +} + +#endif /* CONFIG_AUDIO */ diff --git a/os/drivers/audio/i2schar.c b/os/drivers/audio/i2schar.c index 0fc20d1..6b3f258 100644 --- a/os/drivers/audio/i2schar.c +++ b/os/drivers/audio/i2schar.c @@ -88,6 +88,9 @@ #define CONFIG_AUDIO_I2SCHAR_TXTIMEOUT 0 #endif +#define i2serr printf +#define i2sinfo printf + /* Device naming ************************************************************/ #define DEVNAME_FMT "/dev/i2schar%d" #define DEVNAME_FMTLEN (12 + 3 + 1) diff --git a/os/include/tinyara/audio/audio.h b/os/include/tinyara/audio/audio.h index 7b5f48f..0d68298 100644 --- a/os/include/tinyara/audio/audio.h +++ b/os/include/tinyara/audio/audio.h @@ -79,6 +79,8 @@ #ifdef CONFIG_AUDIO +#define audinfo printf + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -285,13 +287,13 @@ #define AUDIO_ABP_CANDMA 0x0010 /* Set if the data is DMA'able */ #define AUDIO_ABP_STATIC 0x0020 /* Set if statically allocated */ #define AUDIO_ABP_ACTIVE 0x0040 /* Set if this buffer is still active. - * A buffer could become inactive - * if it is processed by an output - * device or a processing device - * that replaces it with an alternate - * buffer as a result of some DSP - * operation, etc. - */ + * A buffer could become inactive + * if it is processed by an output + * device or a processing device + * that replaces it with an alternate + * buffer as a result of some DSP + * operation, etc. + */ /* Standard Audio Message Queue message IDs */ @@ -328,10 +330,10 @@ typedef uint16_t apb_samp_t; /* This structure is used to describe the audio device capabilities */ struct audio_caps_s { - uint8_t ac_len; /* Length of the structure */ - uint8_t ac_type; /* Capabilities (device) type */ - uint8_t ac_subtype; /* Capabilities sub-type, if needed */ - uint8_t ac_channels; /* Number of channels (1, 2, 5, 7) */ + uint8_t ac_len; /* Length of the structure */ + uint8_t ac_type; /* Capabilities (device) type */ + uint8_t ac_subtype; /* Capabilities sub-type, if needed */ + uint8_t ac_channels; /* Number of channels (1, 2, 5, 7) */ union { /* Audio data format(s) for this device */ uint8_t b[2]; @@ -339,8 +341,9 @@ struct audio_caps_s { } ac_format; union { - /* Device specific controls. For AUDIO_DEVICE_QUERY, *//* this field reports the device type supported */ - uint8_t b[4]; /* by this lower-half driver. */ + /* Device specific controls. For AUDIO_DEVICE_QUERY, */ + /* this field reports the device type supported */ + uint8_t b[4]; /* by this lower-half driver. */ uint16_t hw[2]; uint32_t w; } ac_controls; @@ -381,16 +384,16 @@ 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 */ #ifdef CONFIG_AUDIO_MULTI_SESSION - FAR void *session; /* Associated 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; + 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 */ +}; /* Structure defining the messages passed to a listening audio thread * for dequeuing buffers and other operations. Also used to allocate diff --git a/os/include/tinyara/fs/ioctl.h b/os/include/tinyara/fs/ioctl.h index 19ac985..1da95bc 100644 --- a/os/include/tinyara/fs/ioctl.h +++ b/os/include/tinyara/fs/ioctl.h @@ -82,6 +82,7 @@ #define _CAIOCBASE (0x0d00) /* CDC/ACM ioctl commands */ #define _BATIOCBASE (0x0e00) /* Battery driver ioctl commands */ #define _QEIOCBASE (0x0f00) /* Quadrature encoder ioctl commands */ +#define _AUDIOIOCBASE (0x1000) /* Audio ioctl commands */ #define _AUDIOIOCBASE (0x1000) /* Audio ioctl commands */ #define _SLCDIOCBASE (0x1100) /* Segment LCD ioctl commands */ #define _WLIOCBASE (0x1200) /* Wireless modules ioctl commands */ @@ -292,11 +293,10 @@ #define _QEIOCVALID(c) (_IOC_TYPE(c) == _QEIOCBASE) #define _QEIOC(nr) _IOC(_QEIOCBASE, nr) -/* Audio driver ioctl definitions *************************************/ -/* (see tinyara/audio/audio.h) */ +/* Tinyara Audio driver ioctl definitions (see tinyara/audio/audio.h)*************************/ -#define _AUDIOIOCVALID(c) (_IOC_TYPE(c) == _AUDIOIOCBASE) -#define _AUDIOIOC(nr) _IOC(_AUDIOIOCBASE, nr) +#define _AUDIOIOCVALID(c) (_IOC_TYPE(c)==_AUDIOIOCBASE) +#define _AUDIOIOC(nr) _IOC(_AUDIOIOCBASE,nr) /* Application Config Data driver ioctl definitions *************************/ /* (see include/tinyara/configdata.h */