summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/sound/core
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-11 12:28:04 +0530
committerSrikant Patnaik2015-01-11 12:28:04 +0530
commit871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch)
tree8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/sound/core
parent9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff)
downloadFOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/sound/core')
-rw-r--r--ANDROID_3.4.5/sound/core/Kconfig220
-rw-r--r--ANDROID_3.4.5/sound/core/Makefile38
-rw-r--r--ANDROID_3.4.5/sound/core/compress_offload.c773
-rw-r--r--ANDROID_3.4.5/sound/core/control.c1726
-rw-r--r--ANDROID_3.4.5/sound/core/control_compat.c448
-rw-r--r--ANDROID_3.4.5/sound/core/ctljack.c56
-rw-r--r--ANDROID_3.4.5/sound/core/device.c245
-rw-r--r--ANDROID_3.4.5/sound/core/hrtimer.c167
-rw-r--r--ANDROID_3.4.5/sound/core/hwdep.c547
-rw-r--r--ANDROID_3.4.5/sound/core/hwdep_compat.c78
-rw-r--r--ANDROID_3.4.5/sound/core/info.c1016
-rw-r--r--ANDROID_3.4.5/sound/core/info_oss.c139
-rw-r--r--ANDROID_3.4.5/sound/core/init.c991
-rw-r--r--ANDROID_3.4.5/sound/core/isadma.c117
-rw-r--r--ANDROID_3.4.5/sound/core/jack.c242
-rw-r--r--ANDROID_3.4.5/sound/core/memalloc.c547
-rw-r--r--ANDROID_3.4.5/sound/core/memory.c92
-rw-r--r--ANDROID_3.4.5/sound/core/misc.c148
-rw-r--r--ANDROID_3.4.5/sound/core/oss/Makefile13
-rw-r--r--ANDROID_3.4.5/sound/core/oss/copy.c92
-rw-r--r--ANDROID_3.4.5/sound/core/oss/io.c141
-rw-r--r--ANDROID_3.4.5/sound/core/oss/linear.c178
-rw-r--r--ANDROID_3.4.5/sound/core/oss/mixer_oss.c1422
-rw-r--r--ANDROID_3.4.5/sound/core/oss/mulaw.c344
-rw-r--r--ANDROID_3.4.5/sound/core/oss/pcm_oss.c3117
-rw-r--r--ANDROID_3.4.5/sound/core/oss/pcm_plugin.c756
-rw-r--r--ANDROID_3.4.5/sound/core/oss/pcm_plugin.h185
-rw-r--r--ANDROID_3.4.5/sound/core/oss/rate.c348
-rw-r--r--ANDROID_3.4.5/sound/core/oss/route.c109
-rw-r--r--ANDROID_3.4.5/sound/core/pcm.c1220
-rw-r--r--ANDROID_3.4.5/sound/core/pcm_compat.c532
-rw-r--r--ANDROID_3.4.5/sound/core/pcm_lib.c2289
-rw-r--r--ANDROID_3.4.5/sound/core/pcm_memory.c493
-rw-r--r--ANDROID_3.4.5/sound/core/pcm_misc.c490
-rw-r--r--ANDROID_3.4.5/sound/core/pcm_native.c3492
-rw-r--r--ANDROID_3.4.5/sound/core/pcm_timer.c141
-rw-r--r--ANDROID_3.4.5/sound/core/rawmidi.c1726
-rw-r--r--ANDROID_3.4.5/sound/core/rawmidi_compat.c120
-rw-r--r--ANDROID_3.4.5/sound/core/rtctimer.c188
-rw-r--r--ANDROID_3.4.5/sound/core/seq/Kconfig16
-rw-r--r--ANDROID_3.4.5/sound/core/seq/Makefile29
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/Makefile10
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss.c312
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_device.h189
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.c447
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.h112
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_init.c546
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_ioctl.c209
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.c714
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.h48
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.c237
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.h56
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_rw.c216
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.c664
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.h51
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.c284
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.h70
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.c173
-rw-r--r--ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.h50
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq.c137
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_clientmgr.c2591
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_clientmgr.h103
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_compat.c138
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_device.c573
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_dummy.c261
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_fifo.c272
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_fifo.h72
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_info.c72
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_info.h40
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_lock.c49
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_lock.h33
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_memory.c521
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_memory.h107
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_midi.c481
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_midi_emul.c740
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_midi_event.c550
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_ports.c685
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_ports.h142
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_prioq.c453
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_prioq.h62
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_queue.c793
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_queue.h139
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_system.c175
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_system.h46
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_timer.c455
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_timer.h148
-rw-r--r--ANDROID_3.4.5/sound/core/seq/seq_virmidi.c543
-rw-r--r--ANDROID_3.4.5/sound/core/sgbuf.c138
-rw-r--r--ANDROID_3.4.5/sound/core/sound.c491
-rw-r--r--ANDROID_3.4.5/sound/core/sound_oss.c285
-rw-r--r--ANDROID_3.4.5/sound/core/timer.c1999
-rw-r--r--ANDROID_3.4.5/sound/core/timer_compat.c127
-rw-r--r--ANDROID_3.4.5/sound/core/vmaster.c455
93 files changed, 0 insertions, 43295 deletions
diff --git a/ANDROID_3.4.5/sound/core/Kconfig b/ANDROID_3.4.5/sound/core/Kconfig
deleted file mode 100644
index 72261551..00000000
--- a/ANDROID_3.4.5/sound/core/Kconfig
+++ /dev/null
@@ -1,220 +0,0 @@
-# ALSA soundcard-configuration
-config SND_TIMER
- tristate
-
-config SND_PCM
- tristate
- select SND_TIMER
-
-config SND_HWDEP
- tristate
-
-config SND_RAWMIDI
- tristate
-
-config SND_COMPRESS_OFFLOAD
- tristate
-
-# To be effective this also requires INPUT - users should say:
-# select SND_JACK if INPUT=y || INPUT=SND
-# to avoid having to force INPUT on.
-config SND_JACK
- bool
-
-config SND_SEQUENCER
- tristate "Sequencer support"
- select SND_TIMER
- help
- Say Y or M to enable MIDI sequencer and router support. This
- feature allows routing and enqueueing of MIDI events. Events
- can be processed at a given time.
-
- Many programs require this feature, so you should enable it
- unless you know what you're doing.
-
-config SND_SEQ_DUMMY
- tristate "Sequencer dummy client"
- depends on SND_SEQUENCER
- help
- Say Y here to enable the dummy sequencer client. This client
- is a simple MIDI-through client: all normal input events are
- redirected to the output port immediately.
-
- You don't need this unless you want to connect many MIDI
- devices or applications together.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-seq-dummy.
-
-config SND_OSSEMUL
- select SOUND_OSS_CORE
- bool
-
-config SND_MIXER_OSS
- tristate "OSS Mixer API"
- select SND_OSSEMUL
- help
- To enable OSS mixer API emulation (/dev/mixer*), say Y here
- and read <file:Documentation/sound/alsa/OSS-Emulation.txt>.
-
- Many programs still use the OSS API, so say Y.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-mixer-oss.
-
-config SND_PCM_OSS
- tristate "OSS PCM (digital audio) API"
- select SND_OSSEMUL
- select SND_PCM
- help
- To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y
- here and read <file:Documentation/sound/alsa/OSS-Emulation.txt>.
-
- Many programs still use the OSS API, so say Y.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-pcm-oss.
-
-config SND_PCM_OSS_PLUGINS
- bool "OSS PCM (digital audio) API - Include plugin system"
- depends on SND_PCM_OSS
- default y
- help
- If you disable this option, the ALSA's OSS PCM API will not
- support conversion of channels, formats and rates. It will
- behave like most of new OSS/Free drivers in 2.4/2.6 kernels.
-
-config SND_SEQUENCER_OSS
- bool "OSS Sequencer API"
- depends on SND_SEQUENCER
- select SND_OSSEMUL
- help
- Say Y here to enable OSS sequencer emulation (both
- /dev/sequencer and /dev/music interfaces).
-
- Many programs still use the OSS API, so say Y.
-
- If you choose M in "Sequencer support" (SND_SEQUENCER),
- this will be compiled as a module. The module will be called
- snd-seq-oss.
-
-config SND_HRTIMER
- tristate "HR-timer backend support"
- depends on HIGH_RES_TIMERS
- select SND_TIMER
- help
- Say Y here to enable HR-timer backend for ALSA timer. ALSA uses
- the hrtimer as a precise timing source. The ALSA sequencer code
- also can use this timing source.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-hrtimer.
-
-config SND_SEQ_HRTIMER_DEFAULT
- bool "Use HR-timer as default sequencer timer"
- depends on SND_HRTIMER && SND_SEQUENCER
- default y
- help
- Say Y here to use the HR-timer backend as the default sequencer
- timer.
-
-config SND_RTCTIMER
- tristate "RTC Timer support"
- depends on RTC
- select SND_TIMER
- help
- Say Y here to enable RTC timer support for ALSA. ALSA uses
- the RTC timer as a precise timing source and maps the RTC
- timer to ALSA's timer interface. The ALSA sequencer code also
- can use this timing source.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-rtctimer.
-
- Note that this option is exclusive with the new RTC drivers
- (CONFIG_RTC_CLASS) since this requires the old API.
-
-config SND_SEQ_RTCTIMER_DEFAULT
- bool "Use RTC as default sequencer timer"
- depends on SND_RTCTIMER && SND_SEQUENCER
- depends on !SND_SEQ_HRTIMER_DEFAULT
- default y
- help
- Say Y here to use the RTC timer as the default sequencer
- timer. This is strongly recommended because it ensures
- precise MIDI timing even when the system timer runs at less
- than 1000 Hz.
-
- If in doubt, say Y.
-
-config SND_DYNAMIC_MINORS
- bool "Dynamic device file minor numbers"
- help
- If you say Y here, the minor numbers of ALSA device files in
- /dev/snd/ are allocated dynamically. This allows you to have
- more than 8 sound cards, but requires a dynamic device file
- system like udev.
-
- If you are unsure about this, say N here.
-
-config SND_SUPPORT_OLD_API
- bool "Support old ALSA API"
- select SND_HWDEP
- default y
- help
- Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3
- or older).
-
-config SND_VERBOSE_PROCFS
- bool "Verbose procfs contents"
- depends on PROC_FS
- default y
- help
- Say Y here to include code for verbose procfs contents (provides
- useful information to developers when a problem occurs). On the
- other side, it makes the ALSA subsystem larger.
-
-config SND_VERBOSE_PRINTK
- bool "Verbose printk"
- help
- Say Y here to enable verbose log messages. These messages
- will help to identify source file and position containing
- printed messages.
-
- You don't need this unless you're debugging ALSA.
-
-config SND_DEBUG
- bool "Debug"
- help
- Say Y here to enable ALSA debug code.
-
-config SND_DEBUG_VERBOSE
- bool "More verbose debug"
- depends on SND_DEBUG
- help
- Say Y here to enable extra-verbose debugging messages.
-
- Let me repeat: it enables EXTRA-VERBOSE DEBUGGING messages.
- So, say Y only if you are ready to be annoyed.
-
-config SND_PCM_XRUN_DEBUG
- bool "Enable PCM ring buffer overrun/underrun debugging"
- default n
- depends on SND_DEBUG && SND_VERBOSE_PROCFS
- help
- Say Y to enable the PCM ring buffer overrun/underrun debugging.
- It is usually not required, but if you have trouble with
- sound clicking when system is loaded, it may help to determine
- the process or driver which causes the scheduling gaps.
-
-config SND_VMASTER
- bool
-
-config SND_KCTL_JACK
- bool
-
-config SND_DMA_SGBUF
- def_bool y
- depends on X86
-
-source "sound/core/seq/Kconfig"
diff --git a/ANDROID_3.4.5/sound/core/Makefile b/ANDROID_3.4.5/sound/core/Makefile
deleted file mode 100644
index 43d41174..00000000
--- a/ANDROID_3.4.5/sound/core/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Makefile for ALSA
-# Copyright (c) 1999,2001 by Jaroslav Kysela <perex@perex.cz>
-#
-
-snd-y := sound.o init.o memory.o info.o control.o misc.o device.o
-snd-$(CONFIG_ISA_DMA_API) += isadma.o
-snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o
-snd-$(CONFIG_SND_VMASTER) += vmaster.o
-snd-$(CONFIG_SND_KCTL_JACK) += ctljack.o
-snd-$(CONFIG_SND_JACK) += jack.o
-
-snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
- pcm_memory.o
-
-snd-page-alloc-y := memalloc.o
-snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
-
-snd-rawmidi-objs := rawmidi.o
-snd-timer-objs := timer.o
-snd-hrtimer-objs := hrtimer.o
-snd-rtctimer-objs := rtctimer.o
-snd-hwdep-objs := hwdep.o
-
-snd-compress-objs := compress_offload.o
-
-obj-$(CONFIG_SND) += snd.o
-obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o
-obj-$(CONFIG_SND_TIMER) += snd-timer.o
-obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
-obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o
-obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o
-obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
-
-obj-$(CONFIG_SND_OSSEMUL) += oss/
-obj-$(CONFIG_SND_SEQUENCER) += seq/
-
-obj-$(CONFIG_SND_COMPRESS_OFFLOAD) += snd-compress.o
diff --git a/ANDROID_3.4.5/sound/core/compress_offload.c b/ANDROID_3.4.5/sound/core/compress_offload.c
deleted file mode 100644
index a58cf359..00000000
--- a/ANDROID_3.4.5/sound/core/compress_offload.c
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * compress_core.c - compress offload core
- *
- * Copyright (C) 2011 Intel Corporation
- * Authors: Vinod Koul <vinod.koul@linux.intel.com>
- * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
-#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
-
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/uio.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/compress_params.h>
-#include <sound/compress_offload.h>
-#include <sound/compress_driver.h>
-
-/* TODO:
- * - add substream support for multiple devices in case of
- * SND_DYNAMIC_MINORS is not used
- * - Multiple node representation
- * driver should be able to register multiple nodes
- */
-
-static DEFINE_MUTEX(device_mutex);
-
-struct snd_compr_file {
- unsigned long caps;
- struct snd_compr_stream stream;
-};
-
-/*
- * a note on stream states used:
- * we use follwing states in the compressed core
- * SNDRV_PCM_STATE_OPEN: When stream has been opened.
- * SNDRV_PCM_STATE_SETUP: When stream has been initialized. This is done by
- * calling SNDRV_COMPRESS_SET_PARAMS. running streams will come to this
- * state at stop by calling SNDRV_COMPRESS_STOP, or at end of drain.
- * SNDRV_PCM_STATE_RUNNING: When stream has been started and is
- * decoding/encoding and rendering/capturing data.
- * SNDRV_PCM_STATE_DRAINING: When stream is draining current data. This is done
- * by calling SNDRV_COMPRESS_DRAIN.
- * SNDRV_PCM_STATE_PAUSED: When stream is paused. This is done by calling
- * SNDRV_COMPRESS_PAUSE. It can be stopped or resumed by calling
- * SNDRV_COMPRESS_STOP or SNDRV_COMPRESS_RESUME respectively.
- */
-static int snd_compr_open(struct inode *inode, struct file *f)
-{
- struct snd_compr *compr;
- struct snd_compr_file *data;
- struct snd_compr_runtime *runtime;
- enum snd_compr_direction dirn;
- int maj = imajor(inode);
- int ret;
-
- if (f->f_flags & O_WRONLY)
- dirn = SND_COMPRESS_PLAYBACK;
- else if (f->f_flags & O_RDONLY)
- dirn = SND_COMPRESS_CAPTURE;
- else {
- pr_err("invalid direction\n");
- return -EINVAL;
- }
-
- if (maj == snd_major)
- compr = snd_lookup_minor_data(iminor(inode),
- SNDRV_DEVICE_TYPE_COMPRESS);
- else
- return -EBADFD;
-
- if (compr == NULL) {
- pr_err("no device data!!!\n");
- return -ENODEV;
- }
-
- if (dirn != compr->direction) {
- pr_err("this device doesn't support this direction\n");
- snd_card_unref(compr->card);
- return -EINVAL;
- }
-
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data) {
- snd_card_unref(compr->card);
- return -ENOMEM;
- }
- data->stream.ops = compr->ops;
- data->stream.direction = dirn;
- data->stream.private_data = compr->private_data;
- data->stream.device = compr;
- runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
- if (!runtime) {
- kfree(data);
- snd_card_unref(compr->card);
- return -ENOMEM;
- }
- runtime->state = SNDRV_PCM_STATE_OPEN;
- init_waitqueue_head(&runtime->sleep);
- data->stream.runtime = runtime;
- f->private_data = (void *)data;
- mutex_lock(&compr->lock);
- ret = compr->ops->open(&data->stream);
- mutex_unlock(&compr->lock);
- if (ret) {
- kfree(runtime);
- kfree(data);
- }
- snd_card_unref(compr->card);
- return 0;
-}
-
-static int snd_compr_free(struct inode *inode, struct file *f)
-{
- struct snd_compr_file *data = f->private_data;
- data->stream.ops->free(&data->stream);
- kfree(data->stream.runtime->buffer);
- kfree(data->stream.runtime);
- kfree(data);
- return 0;
-}
-
-static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
- struct snd_compr_tstamp *tstamp)
-{
- if (!stream->ops->pointer)
- return;
- stream->ops->pointer(stream, tstamp);
- pr_debug("dsp consumed till %d total %d bytes\n",
- tstamp->byte_offset, tstamp->copied_total);
- stream->runtime->hw_pointer = tstamp->byte_offset;
- stream->runtime->total_bytes_transferred = tstamp->copied_total;
-}
-
-static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
- struct snd_compr_avail *avail)
-{
- long avail_calc; /*this needs to be signed variable */
-
- snd_compr_update_tstamp(stream, &avail->tstamp);
-
- /* FIXME: This needs to be different for capture stream,
- available is # of compressed data, for playback it's
- remainder of buffer */
-
- if (stream->runtime->total_bytes_available == 0 &&
- stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
- pr_debug("detected init and someone forgot to do a write\n");
- return stream->runtime->buffer_size;
- }
- pr_debug("app wrote %lld, DSP consumed %lld\n",
- stream->runtime->total_bytes_available,
- stream->runtime->total_bytes_transferred);
- if (stream->runtime->total_bytes_available ==
- stream->runtime->total_bytes_transferred) {
- pr_debug("both pointers are same, returning full avail\n");
- return stream->runtime->buffer_size;
- }
-
- /* FIXME: this routine isn't consistent, in one test we use
- * cumulative values and in the other byte offsets. Do we
- * really need the byte offsets if the cumulative values have
- * been updated? In the PCM interface app_ptr and hw_ptr are
- * already cumulative */
-
- avail_calc = stream->runtime->buffer_size -
- (stream->runtime->app_pointer - stream->runtime->hw_pointer);
- pr_debug("calc avail as %ld, app_ptr %lld, hw+ptr %lld\n", avail_calc,
- stream->runtime->app_pointer,
- stream->runtime->hw_pointer);
- if (avail_calc >= stream->runtime->buffer_size)
- avail_calc -= stream->runtime->buffer_size;
- pr_debug("ret avail as %ld\n", avail_calc);
- avail->avail = avail_calc;
- return avail_calc;
-}
-
-static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
-{
- struct snd_compr_avail avail;
-
- return snd_compr_calc_avail(stream, &avail);
-}
-
-static int
-snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
-{
- struct snd_compr_avail ioctl_avail;
- size_t avail;
-
- avail = snd_compr_calc_avail(stream, &ioctl_avail);
- ioctl_avail.avail = avail;
-
- if (copy_to_user((__u64 __user *)arg,
- &ioctl_avail, sizeof(ioctl_avail)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_compr_write_data(struct snd_compr_stream *stream,
- const char __user *buf, size_t count)
-{
- void *dstn;
- size_t copy;
- struct snd_compr_runtime *runtime = stream->runtime;
-
- dstn = runtime->buffer + runtime->app_pointer;
- pr_debug("copying %ld at %lld\n",
- (unsigned long)count, runtime->app_pointer);
- if (count < runtime->buffer_size - runtime->app_pointer) {
- if (copy_from_user(dstn, buf, count))
- return -EFAULT;
- runtime->app_pointer += count;
- } else {
- copy = runtime->buffer_size - runtime->app_pointer;
- if (copy_from_user(dstn, buf, copy))
- return -EFAULT;
- if (copy_from_user(runtime->buffer, buf + copy, count - copy))
- return -EFAULT;
- runtime->app_pointer = count - copy;
- }
- /* if DSP cares, let it know data has been written */
- if (stream->ops->ack)
- stream->ops->ack(stream, count);
- return count;
-}
-
-static ssize_t snd_compr_write(struct file *f, const char __user *buf,
- size_t count, loff_t *offset)
-{
- struct snd_compr_file *data = f->private_data;
- struct snd_compr_stream *stream;
- size_t avail;
- int retval;
-
- if (snd_BUG_ON(!data))
- return -EFAULT;
-
- stream = &data->stream;
- mutex_lock(&stream->device->lock);
- /* write is allowed when stream is running or has been steup */
- if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
- stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
- mutex_unlock(&stream->device->lock);
- return -EBADFD;
- }
-
- avail = snd_compr_get_avail(stream);
- pr_debug("avail returned %ld\n", (unsigned long)avail);
- /* calculate how much we can write to buffer */
- if (avail > count)
- avail = count;
-
- if (stream->ops->copy)
- retval = stream->ops->copy(stream, buf, avail);
- else
- retval = snd_compr_write_data(stream, buf, avail);
- if (retval > 0)
- stream->runtime->total_bytes_available += retval;
-
- /* while initiating the stream, write should be called before START
- * call, so in setup move state */
- if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
- stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
- pr_debug("stream prepared, Houston we are good to go\n");
- }
-
- mutex_unlock(&stream->device->lock);
- return retval;
-}
-
-
-static ssize_t snd_compr_read(struct file *f, char __user *buf,
- size_t count, loff_t *offset)
-{
- return -ENXIO;
-}
-
-static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
-{
- return -ENXIO;
-}
-
-static inline int snd_compr_get_poll(struct snd_compr_stream *stream)
-{
- if (stream->direction == SND_COMPRESS_PLAYBACK)
- return POLLOUT | POLLWRNORM;
- else
- return POLLIN | POLLRDNORM;
-}
-
-static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
-{
- struct snd_compr_file *data = f->private_data;
- struct snd_compr_stream *stream;
- size_t avail;
- int retval = 0;
-
- if (snd_BUG_ON(!data))
- return -EFAULT;
- stream = &data->stream;
- if (snd_BUG_ON(!stream))
- return -EFAULT;
-
- mutex_lock(&stream->device->lock);
- if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED ||
- stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
- retval = -EBADFD;
- goto out;
- }
- poll_wait(f, &stream->runtime->sleep, wait);
-
- avail = snd_compr_get_avail(stream);
- pr_debug("avail is %ld\n", (unsigned long)avail);
- /* check if we have at least one fragment to fill */
- switch (stream->runtime->state) {
- case SNDRV_PCM_STATE_DRAINING:
- /* stream has been woken up after drain is complete
- * draining done so set stream state to stopped
- */
- retval = snd_compr_get_poll(stream);
- stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- break;
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_PAUSED:
- if (avail >= stream->runtime->fragment_size)
- retval = snd_compr_get_poll(stream);
- break;
- default:
- if (stream->direction == SND_COMPRESS_PLAYBACK)
- retval = POLLOUT | POLLWRNORM | POLLERR;
- else
- retval = POLLIN | POLLRDNORM | POLLERR;
- break;
- }
-out:
- mutex_unlock(&stream->device->lock);
- return retval;
-}
-
-static int
-snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
-{
- int retval;
- struct snd_compr_caps caps;
-
- if (!stream->ops->get_caps)
- return -ENXIO;
-
- retval = stream->ops->get_caps(stream, &caps);
- if (retval)
- goto out;
- if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
- retval = -EFAULT;
-out:
- return retval;
-}
-
-static int
-snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
-{
- int retval;
- struct snd_compr_codec_caps *caps;
-
- if (!stream->ops->get_codec_caps)
- return -ENXIO;
-
- caps = kmalloc(sizeof(*caps), GFP_KERNEL);
- if (!caps)
- return -ENOMEM;
-
- retval = stream->ops->get_codec_caps(stream, caps);
- if (retval)
- goto out;
- if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
- retval = -EFAULT;
-
-out:
- kfree(caps);
- return retval;
-}
-
-/* revisit this with snd_pcm_preallocate_xxx */
-static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
- struct snd_compr_params *params)
-{
- unsigned int buffer_size;
- void *buffer;
-
- buffer_size = params->buffer.fragment_size * params->buffer.fragments;
- if (stream->ops->copy) {
- buffer = NULL;
- /* if copy is defined the driver will be required to copy
- * the data from core
- */
- } else {
- buffer = kmalloc(buffer_size, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
- }
- stream->runtime->fragment_size = params->buffer.fragment_size;
- stream->runtime->fragments = params->buffer.fragments;
- stream->runtime->buffer = buffer;
- stream->runtime->buffer_size = buffer_size;
- return 0;
-}
-
-static int
-snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
-{
- struct snd_compr_params *params;
- int retval;
-
- if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
- /*
- * we should allow parameter change only when stream has been
- * opened not in other cases
- */
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params)
- return -ENOMEM;
- if (copy_from_user(params, (void __user *)arg, sizeof(*params))) {
- retval = -EFAULT;
- goto out;
- }
- retval = snd_compr_allocate_buffer(stream, params);
- if (retval) {
- retval = -ENOMEM;
- goto out;
- }
- retval = stream->ops->set_params(stream, params);
- if (retval)
- goto out;
- stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- } else {
- return -EPERM;
- }
-out:
- kfree(params);
- return retval;
-}
-
-static int
-snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
-{
- struct snd_codec *params;
- int retval;
-
- if (!stream->ops->get_params)
- return -EBADFD;
-
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params)
- return -ENOMEM;
- retval = stream->ops->get_params(stream, params);
- if (retval)
- goto out;
- if (copy_to_user((char __user *)arg, params, sizeof(*params)))
- retval = -EFAULT;
-
-out:
- kfree(params);
- return retval;
-}
-
-static inline int
-snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
-{
- struct snd_compr_tstamp tstamp;
-
- snd_compr_update_tstamp(stream, &tstamp);
- return copy_to_user((struct snd_compr_tstamp __user *)arg,
- &tstamp, sizeof(tstamp)) ? -EFAULT : 0;
-}
-
-static int snd_compr_pause(struct snd_compr_stream *stream)
-{
- int retval;
-
- if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
- return -EPERM;
- retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
- if (!retval) {
- stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
- wake_up(&stream->runtime->sleep);
- }
- return retval;
-}
-
-static int snd_compr_resume(struct snd_compr_stream *stream)
-{
- int retval;
-
- if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
- return -EPERM;
- retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
- if (!retval)
- stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
- return retval;
-}
-
-static int snd_compr_start(struct snd_compr_stream *stream)
-{
- int retval;
-
- if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
- return -EPERM;
- retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
- if (!retval)
- stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
- return retval;
-}
-
-static int snd_compr_stop(struct snd_compr_stream *stream)
-{
- int retval;
-
- if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
- stream->runtime->state == SNDRV_PCM_STATE_SETUP)
- return -EPERM;
- retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
- if (!retval) {
- stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- wake_up(&stream->runtime->sleep);
- }
- return retval;
-}
-
-static int snd_compr_drain(struct snd_compr_stream *stream)
-{
- int retval;
-
- if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
- stream->runtime->state == SNDRV_PCM_STATE_SETUP)
- return -EPERM;
- retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
- if (!retval) {
- stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
- wake_up(&stream->runtime->sleep);
- }
- return retval;
-}
-
-static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
-{
- struct snd_compr_file *data = f->private_data;
- struct snd_compr_stream *stream;
- int retval = -ENOTTY;
-
- if (snd_BUG_ON(!data))
- return -EFAULT;
- stream = &data->stream;
- if (snd_BUG_ON(!stream))
- return -EFAULT;
- mutex_lock(&stream->device->lock);
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
- put_user(SNDRV_COMPRESS_VERSION,
- (int __user *)arg) ? -EFAULT : 0;
- break;
- case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
- retval = snd_compr_get_caps(stream, arg);
- break;
- case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
- retval = snd_compr_get_codec_caps(stream, arg);
- break;
- case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
- retval = snd_compr_set_params(stream, arg);
- break;
- case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
- retval = snd_compr_get_params(stream, arg);
- break;
- case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
- retval = snd_compr_tstamp(stream, arg);
- break;
- case _IOC_NR(SNDRV_COMPRESS_AVAIL):
- retval = snd_compr_ioctl_avail(stream, arg);
- break;
- case _IOC_NR(SNDRV_COMPRESS_PAUSE):
- retval = snd_compr_pause(stream);
- break;
- case _IOC_NR(SNDRV_COMPRESS_RESUME):
- retval = snd_compr_resume(stream);
- break;
- case _IOC_NR(SNDRV_COMPRESS_START):
- retval = snd_compr_start(stream);
- break;
- case _IOC_NR(SNDRV_COMPRESS_STOP):
- retval = snd_compr_stop(stream);
- break;
- case _IOC_NR(SNDRV_COMPRESS_DRAIN):
- retval = snd_compr_drain(stream);
- break;
- }
- mutex_unlock(&stream->device->lock);
- return retval;
-}
-
-static const struct file_operations snd_compr_file_ops = {
- .owner = THIS_MODULE,
- .open = snd_compr_open,
- .release = snd_compr_free,
- .write = snd_compr_write,
- .read = snd_compr_read,
- .unlocked_ioctl = snd_compr_ioctl,
- .mmap = snd_compr_mmap,
- .poll = snd_compr_poll,
-};
-
-static int snd_compress_dev_register(struct snd_device *device)
-{
- int ret = -EINVAL;
- char str[16];
- struct snd_compr *compr;
-
- if (snd_BUG_ON(!device || !device->device_data))
- return -EBADFD;
- compr = device->device_data;
-
- sprintf(str, "comprC%iD%i", compr->card->number, compr->device);
- pr_debug("reg %s for device %s, direction %d\n", str, compr->name,
- compr->direction);
- /* register compressed device */
- ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card,
- compr->device, &snd_compr_file_ops, compr, str);
- if (ret < 0) {
- pr_err("snd_register_device failed\n %d", ret);
- return ret;
- }
- return ret;
-
-}
-
-static int snd_compress_dev_disconnect(struct snd_device *device)
-{
- struct snd_compr *compr;
-
- compr = device->device_data;
- snd_unregister_device(compr->direction, compr->card, compr->device);
- return 0;
-}
-
-/*
- * snd_compress_new: create new compress device
- * @card: sound card pointer
- * @device: device number
- * @dirn: device direction, should be of type enum snd_compr_direction
- * @compr: compress device pointer
- */
-int snd_compress_new(struct snd_card *card, int device,
- int dirn, struct snd_compr *compr)
-{
- static struct snd_device_ops ops = {
- .dev_free = NULL,
- .dev_register = snd_compress_dev_register,
- .dev_disconnect = snd_compress_dev_disconnect,
- };
-
- compr->card = card;
- compr->device = device;
- compr->direction = dirn;
- return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
-}
-EXPORT_SYMBOL_GPL(snd_compress_new);
-
-static int snd_compress_add_device(struct snd_compr *device)
-{
- int ret;
-
- if (!device->card)
- return -EINVAL;
-
- /* register the card */
- ret = snd_card_register(device->card);
- if (ret)
- goto out;
- return 0;
-
-out:
- pr_err("failed with %d\n", ret);
- return ret;
-
-}
-
-static int snd_compress_remove_device(struct snd_compr *device)
-{
- return snd_card_free(device->card);
-}
-
-/**
- * snd_compress_register - register compressed device
- *
- * @device: compressed device to register
- */
-int snd_compress_register(struct snd_compr *device)
-{
- int retval;
-
- if (device->name == NULL || device->dev == NULL || device->ops == NULL)
- return -EINVAL;
-
- pr_debug("Registering compressed device %s\n", device->name);
- if (snd_BUG_ON(!device->ops->open))
- return -EINVAL;
- if (snd_BUG_ON(!device->ops->free))
- return -EINVAL;
- if (snd_BUG_ON(!device->ops->set_params))
- return -EINVAL;
- if (snd_BUG_ON(!device->ops->trigger))
- return -EINVAL;
-
- mutex_init(&device->lock);
-
- /* register a compressed card */
- mutex_lock(&device_mutex);
- retval = snd_compress_add_device(device);
- mutex_unlock(&device_mutex);
- return retval;
-}
-EXPORT_SYMBOL_GPL(snd_compress_register);
-
-int snd_compress_deregister(struct snd_compr *device)
-{
- pr_debug("Removing compressed device %s\n", device->name);
- mutex_lock(&device_mutex);
- snd_compress_remove_device(device);
- mutex_unlock(&device_mutex);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_compress_deregister);
-
-static int __init snd_compress_init(void)
-{
- return 0;
-}
-
-static void __exit snd_compress_exit(void)
-{
-}
-
-module_init(snd_compress_init);
-module_exit(snd_compress_exit);
-
-MODULE_DESCRIPTION("ALSA Compressed offload framework");
-MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/ANDROID_3.4.5/sound/core/control.c b/ANDROID_3.4.5/sound/core/control.c
deleted file mode 100644
index daa4fc88..00000000
--- a/ANDROID_3.4.5/sound/core/control.c
+++ /dev/null
@@ -1,1726 +0,0 @@
-/*
- * Routines for driver control interface
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/time.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <sound/info.h>
-#include <sound/control.h>
-
-/* max number of user-defined controls */
-#define MAX_USER_CONTROLS 32
-#define MAX_CONTROL_COUNT 1028
-
-struct snd_kctl_ioctl {
- struct list_head list; /* list of all ioctls */
- snd_kctl_ioctl_func_t fioctl;
-};
-
-static DECLARE_RWSEM(snd_ioctl_rwsem);
-static LIST_HEAD(snd_control_ioctls);
-#ifdef CONFIG_COMPAT
-static LIST_HEAD(snd_control_compat_ioctls);
-#endif
-
-static int snd_ctl_open(struct inode *inode, struct file *file)
-{
- unsigned long flags;
- struct snd_card *card;
- struct snd_ctl_file *ctl;
- int err;
-
- err = nonseekable_open(inode, file);
- if (err < 0)
- return err;
-
- card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
- if (!card) {
- err = -ENODEV;
- goto __error1;
- }
- err = snd_card_file_add(card, file);
- if (err < 0) {
- err = -ENODEV;
- goto __error1;
- }
- if (!try_module_get(card->module)) {
- err = -EFAULT;
- goto __error2;
- }
- ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
- if (ctl == NULL) {
- err = -ENOMEM;
- goto __error;
- }
- INIT_LIST_HEAD(&ctl->events);
- init_waitqueue_head(&ctl->change_sleep);
- spin_lock_init(&ctl->read_lock);
- ctl->card = card;
- ctl->prefer_pcm_subdevice = -1;
- ctl->prefer_rawmidi_subdevice = -1;
- ctl->pid = get_pid(task_pid(current));
- file->private_data = ctl;
- write_lock_irqsave(&card->ctl_files_rwlock, flags);
- list_add_tail(&ctl->list, &card->ctl_files);
- write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
- snd_card_unref(card);
- return 0;
-
- __error:
- module_put(card->module);
- __error2:
- snd_card_file_remove(card, file);
- __error1:
- if (card)
- snd_card_unref(card);
- return err;
-}
-
-static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
-{
- unsigned long flags;
- struct snd_kctl_event *cread;
-
- spin_lock_irqsave(&ctl->read_lock, flags);
- while (!list_empty(&ctl->events)) {
- cread = snd_kctl_event(ctl->events.next);
- list_del(&cread->list);
- kfree(cread);
- }
- spin_unlock_irqrestore(&ctl->read_lock, flags);
-}
-
-static int snd_ctl_release(struct inode *inode, struct file *file)
-{
- unsigned long flags;
- struct snd_card *card;
- struct snd_ctl_file *ctl;
- struct snd_kcontrol *control;
- unsigned int idx;
-
- ctl = file->private_data;
- file->private_data = NULL;
- card = ctl->card;
- write_lock_irqsave(&card->ctl_files_rwlock, flags);
- list_del(&ctl->list);
- write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
- down_write(&card->controls_rwsem);
- list_for_each_entry(control, &card->controls, list)
- for (idx = 0; idx < control->count; idx++)
- if (control->vd[idx].owner == ctl)
- control->vd[idx].owner = NULL;
- up_write(&card->controls_rwsem);
- snd_ctl_empty_read_queue(ctl);
- put_pid(ctl->pid);
- kfree(ctl);
- module_put(card->module);
- snd_card_file_remove(card, file);
- return 0;
-}
-
-void snd_ctl_notify(struct snd_card *card, unsigned int mask,
- struct snd_ctl_elem_id *id)
-{
- unsigned long flags;
- struct snd_ctl_file *ctl;
- struct snd_kctl_event *ev;
-
- if (snd_BUG_ON(!card || !id))
- return;
- read_lock(&card->ctl_files_rwlock);
-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
- card->mixer_oss_change_count++;
-#endif
- list_for_each_entry(ctl, &card->ctl_files, list) {
- if (!ctl->subscribed)
- continue;
- spin_lock_irqsave(&ctl->read_lock, flags);
- list_for_each_entry(ev, &ctl->events, list) {
- if (ev->id.numid == id->numid) {
- ev->mask |= mask;
- goto _found;
- }
- }
- ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
- if (ev) {
- ev->id = *id;
- ev->mask = mask;
- list_add_tail(&ev->list, &ctl->events);
- } else {
- snd_printk(KERN_ERR "No memory available to allocate event\n");
- }
- _found:
- wake_up(&ctl->change_sleep);
- spin_unlock_irqrestore(&ctl->read_lock, flags);
- kill_fasync(&ctl->fasync, SIGIO, POLL_IN);
- }
- read_unlock(&card->ctl_files_rwlock);
-}
-
-EXPORT_SYMBOL(snd_ctl_notify);
-
-/**
- * snd_ctl_new - create a control instance from the template
- * @control: the control template
- * @access: the default control access
- *
- * Allocates a new struct snd_kcontrol instance and copies the given template
- * to the new instance. It does not copy volatile data (access).
- *
- * Returns the pointer of the new instance, or NULL on failure.
- */
-static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
- unsigned int access)
-{
- struct snd_kcontrol *kctl;
- unsigned int idx;
-
- if (snd_BUG_ON(!control || !control->count))
- return NULL;
-
- if (control->count > MAX_CONTROL_COUNT)
- return NULL;
-
- kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL);
- if (kctl == NULL) {
- snd_printk(KERN_ERR "Cannot allocate control instance\n");
- return NULL;
- }
- *kctl = *control;
- for (idx = 0; idx < kctl->count; idx++)
- kctl->vd[idx].access = access;
- return kctl;
-}
-
-/**
- * snd_ctl_new1 - create a control instance from the template
- * @ncontrol: the initialization record
- * @private_data: the private data to set
- *
- * Allocates a new struct snd_kcontrol instance and initialize from the given
- * template. When the access field of ncontrol is 0, it's assumed as
- * READWRITE access. When the count field is 0, it's assumes as one.
- *
- * Returns the pointer of the newly generated instance, or NULL on failure.
- */
-struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
- void *private_data)
-{
- struct snd_kcontrol kctl;
- unsigned int access;
-
- if (snd_BUG_ON(!ncontrol || !ncontrol->info))
- return NULL;
- memset(&kctl, 0, sizeof(kctl));
- kctl.id.iface = ncontrol->iface;
- kctl.id.device = ncontrol->device;
- kctl.id.subdevice = ncontrol->subdevice;
- if (ncontrol->name) {
- strlcpy(kctl.id.name, ncontrol->name, sizeof(kctl.id.name));
- if (strcmp(ncontrol->name, kctl.id.name) != 0)
- snd_printk(KERN_WARNING
- "Control name '%s' truncated to '%s'\n",
- ncontrol->name, kctl.id.name);
- }
- kctl.id.index = ncontrol->index;
- kctl.count = ncontrol->count ? ncontrol->count : 1;
- access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
- (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
- SNDRV_CTL_ELEM_ACCESS_INACTIVE|
- SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE|
- SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND|
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK));
- kctl.info = ncontrol->info;
- kctl.get = ncontrol->get;
- kctl.put = ncontrol->put;
- kctl.tlv.p = ncontrol->tlv.p;
- kctl.private_value = ncontrol->private_value;
- kctl.private_data = private_data;
- return snd_ctl_new(&kctl, access);
-}
-
-EXPORT_SYMBOL(snd_ctl_new1);
-
-/**
- * snd_ctl_free_one - release the control instance
- * @kcontrol: the control instance
- *
- * Releases the control instance created via snd_ctl_new()
- * or snd_ctl_new1().
- * Don't call this after the control was added to the card.
- */
-void snd_ctl_free_one(struct snd_kcontrol *kcontrol)
-{
- if (kcontrol) {
- if (kcontrol->private_free)
- kcontrol->private_free(kcontrol);
- kfree(kcontrol);
- }
-}
-
-EXPORT_SYMBOL(snd_ctl_free_one);
-
-static bool snd_ctl_remove_numid_conflict(struct snd_card *card,
- unsigned int count)
-{
- struct snd_kcontrol *kctl;
-
- list_for_each_entry(kctl, &card->controls, list) {
- if (kctl->id.numid < card->last_numid + 1 + count &&
- kctl->id.numid + kctl->count > card->last_numid + 1) {
- card->last_numid = kctl->id.numid + kctl->count - 1;
- return true;
- }
- }
- return false;
-}
-
-static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
-{
- unsigned int iter = 100000;
-
- while (snd_ctl_remove_numid_conflict(card, count)) {
- if (--iter == 0) {
- /* this situation is very unlikely */
- snd_printk(KERN_ERR "unable to allocate new control numid\n");
- return -ENOMEM;
- }
- }
- return 0;
-}
-
-/**
- * snd_ctl_add - add the control instance to the card
- * @card: the card instance
- * @kcontrol: the control instance to add
- *
- * Adds the control instance created via snd_ctl_new() or
- * snd_ctl_new1() to the given card. Assigns also an unique
- * numid used for fast search.
- *
- * Returns zero if successful, or a negative error code on failure.
- *
- * It frees automatically the control which cannot be added.
- */
-int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
-{
- struct snd_ctl_elem_id id;
- unsigned int idx;
- int err = -EINVAL;
-
- if (! kcontrol)
- return err;
- if (snd_BUG_ON(!card || !kcontrol->info))
- goto error;
- id = kcontrol->id;
- down_write(&card->controls_rwsem);
- if (snd_ctl_find_id(card, &id)) {
- up_write(&card->controls_rwsem);
- snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n",
- id.iface,
- id.device,
- id.subdevice,
- id.name,
- id.index);
- err = -EBUSY;
- goto error;
- }
- if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
- up_write(&card->controls_rwsem);
- err = -ENOMEM;
- goto error;
- }
- list_add_tail(&kcontrol->list, &card->controls);
- card->controls_count += kcontrol->count;
- kcontrol->id.numid = card->last_numid + 1;
- card->last_numid += kcontrol->count;
- up_write(&card->controls_rwsem);
- for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
- return 0;
-
- error:
- snd_ctl_free_one(kcontrol);
- return err;
-}
-
-EXPORT_SYMBOL(snd_ctl_add);
-
-/**
- * snd_ctl_replace - replace the control instance of the card
- * @card: the card instance
- * @kcontrol: the control instance to replace
- * @add_on_replace: add the control if not already added
- *
- * Replaces the given control. If the given control does not exist
- * and the add_on_replace flag is set, the control is added. If the
- * control exists, it is destroyed first.
- *
- * Returns zero if successful, or a negative error code on failure.
- *
- * It frees automatically the control which cannot be added or replaced.
- */
-int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
- bool add_on_replace)
-{
- struct snd_ctl_elem_id id;
- unsigned int idx;
- struct snd_kcontrol *old;
- int ret;
-
- if (!kcontrol)
- return -EINVAL;
- if (snd_BUG_ON(!card || !kcontrol->info)) {
- ret = -EINVAL;
- goto error;
- }
- id = kcontrol->id;
- down_write(&card->controls_rwsem);
- old = snd_ctl_find_id(card, &id);
- if (!old) {
- if (add_on_replace)
- goto add;
- up_write(&card->controls_rwsem);
- ret = -EINVAL;
- goto error;
- }
- ret = snd_ctl_remove(card, old);
- if (ret < 0) {
- up_write(&card->controls_rwsem);
- goto error;
- }
-add:
- if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
- up_write(&card->controls_rwsem);
- ret = -ENOMEM;
- goto error;
- }
- list_add_tail(&kcontrol->list, &card->controls);
- card->controls_count += kcontrol->count;
- kcontrol->id.numid = card->last_numid + 1;
- card->last_numid += kcontrol->count;
- up_write(&card->controls_rwsem);
- for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
- return 0;
-
-error:
- snd_ctl_free_one(kcontrol);
- return ret;
-}
-EXPORT_SYMBOL(snd_ctl_replace);
-
-/**
- * snd_ctl_remove - remove the control from the card and release it
- * @card: the card instance
- * @kcontrol: the control instance to remove
- *
- * Removes the control from the card and then releases the instance.
- * You don't need to call snd_ctl_free_one(). You must be in
- * the write lock - down_write(&card->controls_rwsem).
- *
- * Returns 0 if successful, or a negative error code on failure.
- */
-int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
-{
- struct snd_ctl_elem_id id;
- unsigned int idx;
-
- if (snd_BUG_ON(!card || !kcontrol))
- return -EINVAL;
- list_del(&kcontrol->list);
- card->controls_count -= kcontrol->count;
- id = kcontrol->id;
- for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &id);
- snd_ctl_free_one(kcontrol);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_ctl_remove);
-
-/**
- * snd_ctl_remove_id - remove the control of the given id and release it
- * @card: the card instance
- * @id: the control id to remove
- *
- * Finds the control instance with the given id, removes it from the
- * card list and releases it.
- *
- * Returns 0 if successful, or a negative error code on failure.
- */
-int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
-{
- struct snd_kcontrol *kctl;
- int ret;
-
- down_write(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, id);
- if (kctl == NULL) {
- up_write(&card->controls_rwsem);
- return -ENOENT;
- }
- ret = snd_ctl_remove(card, kctl);
- up_write(&card->controls_rwsem);
- return ret;
-}
-
-EXPORT_SYMBOL(snd_ctl_remove_id);
-
-/**
- * snd_ctl_remove_user_ctl - remove and release the unlocked user control
- * @file: active control handle
- * @id: the control id to remove
- *
- * Finds the control instance with the given id, removes it from the
- * card list and releases it.
- *
- * Returns 0 if successful, or a negative error code on failure.
- */
-static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
- struct snd_ctl_elem_id *id)
-{
- struct snd_card *card = file->card;
- struct snd_kcontrol *kctl;
- int idx, ret;
-
- down_write(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, id);
- if (kctl == NULL) {
- ret = -ENOENT;
- goto error;
- }
- if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) {
- ret = -EINVAL;
- goto error;
- }
- for (idx = 0; idx < kctl->count; idx++)
- if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) {
- ret = -EBUSY;
- goto error;
- }
- ret = snd_ctl_remove(card, kctl);
- if (ret < 0)
- goto error;
- card->user_ctl_count--;
-error:
- up_write(&card->controls_rwsem);
- return ret;
-}
-
-/**
- * snd_ctl_activate_id - activate/inactivate the control of the given id
- * @card: the card instance
- * @id: the control id to activate/inactivate
- * @active: non-zero to activate
- *
- * Finds the control instance with the given id, and activate or
- * inactivate the control together with notification, if changed.
- *
- * Returns 0 if unchanged, 1 if changed, or a negative error code on failure.
- */
-int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
- int active)
-{
- struct snd_kcontrol *kctl;
- struct snd_kcontrol_volatile *vd;
- unsigned int index_offset;
- int ret;
-
- down_write(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, id);
- if (kctl == NULL) {
- ret = -ENOENT;
- goto unlock;
- }
- index_offset = snd_ctl_get_ioff(kctl, &kctl->id);
- vd = &kctl->vd[index_offset];
- ret = 0;
- if (active) {
- if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE))
- goto unlock;
- vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
- } else {
- if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)
- goto unlock;
- vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
- }
- ret = 1;
- unlock:
- up_write(&card->controls_rwsem);
- if (ret > 0)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
-
-/**
- * snd_ctl_rename_id - replace the id of a control on the card
- * @card: the card instance
- * @src_id: the old id
- * @dst_id: the new id
- *
- * Finds the control with the old id from the card, and replaces the
- * id with the new one.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
- struct snd_ctl_elem_id *dst_id)
-{
- struct snd_kcontrol *kctl;
-
- down_write(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, src_id);
- if (kctl == NULL) {
- up_write(&card->controls_rwsem);
- return -ENOENT;
- }
- kctl->id = *dst_id;
- kctl->id.numid = card->last_numid + 1;
- card->last_numid += kctl->count;
- up_write(&card->controls_rwsem);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_ctl_rename_id);
-
-/**
- * snd_ctl_find_numid - find the control instance with the given number-id
- * @card: the card instance
- * @numid: the number-id to search
- *
- * Finds the control instance with the given number-id from the card.
- *
- * Returns the pointer of the instance if found, or NULL if not.
- *
- * The caller must down card->controls_rwsem before calling this function
- * (if the race condition can happen).
- */
-struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
-{
- struct snd_kcontrol *kctl;
-
- if (snd_BUG_ON(!card || !numid))
- return NULL;
- list_for_each_entry(kctl, &card->controls, list) {
- if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
- return kctl;
- }
- return NULL;
-}
-
-EXPORT_SYMBOL(snd_ctl_find_numid);
-
-/**
- * snd_ctl_find_id - find the control instance with the given id
- * @card: the card instance
- * @id: the id to search
- *
- * Finds the control instance with the given id from the card.
- *
- * Returns the pointer of the instance if found, or NULL if not.
- *
- * The caller must down card->controls_rwsem before calling this function
- * (if the race condition can happen).
- */
-struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
- struct snd_ctl_elem_id *id)
-{
- struct snd_kcontrol *kctl;
-
- if (snd_BUG_ON(!card || !id))
- return NULL;
- if (id->numid != 0)
- return snd_ctl_find_numid(card, id->numid);
- list_for_each_entry(kctl, &card->controls, list) {
- if (kctl->id.iface != id->iface)
- continue;
- if (kctl->id.device != id->device)
- continue;
- if (kctl->id.subdevice != id->subdevice)
- continue;
- if (strncmp(kctl->id.name, id->name, sizeof(kctl->id.name)))
- continue;
- if (kctl->id.index > id->index)
- continue;
- if (kctl->id.index + kctl->count <= id->index)
- continue;
- return kctl;
- }
- return NULL;
-}
-
-EXPORT_SYMBOL(snd_ctl_find_id);
-
-static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
- unsigned int cmd, void __user *arg)
-{
- struct snd_ctl_card_info *info;
-
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (! info)
- return -ENOMEM;
- down_read(&snd_ioctl_rwsem);
- info->card = card->number;
- strlcpy(info->id, card->id, sizeof(info->id));
- strlcpy(info->driver, card->driver, sizeof(info->driver));
- strlcpy(info->name, card->shortname, sizeof(info->name));
- strlcpy(info->longname, card->longname, sizeof(info->longname));
- strlcpy(info->mixername, card->mixername, sizeof(info->mixername));
- strlcpy(info->components, card->components, sizeof(info->components));
- up_read(&snd_ioctl_rwsem);
- if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) {
- kfree(info);
- return -EFAULT;
- }
- kfree(info);
- return 0;
-}
-
-static int snd_ctl_elem_list(struct snd_card *card,
- struct snd_ctl_elem_list __user *_list)
-{
- struct list_head *plist;
- struct snd_ctl_elem_list list;
- struct snd_kcontrol *kctl;
- struct snd_ctl_elem_id *dst, *id;
- unsigned int offset, space, jidx;
-
- if (copy_from_user(&list, _list, sizeof(list)))
- return -EFAULT;
- offset = list.offset;
- space = list.space;
- /* try limit maximum space */
- if (space > 16384)
- return -ENOMEM;
- if (space > 0) {
- /* allocate temporary buffer for atomic operation */
- dst = vmalloc(space * sizeof(struct snd_ctl_elem_id));
- if (dst == NULL)
- return -ENOMEM;
- down_read(&card->controls_rwsem);
- list.count = card->controls_count;
- plist = card->controls.next;
- while (plist != &card->controls) {
- if (offset == 0)
- break;
- kctl = snd_kcontrol(plist);
- if (offset < kctl->count)
- break;
- offset -= kctl->count;
- plist = plist->next;
- }
- list.used = 0;
- id = dst;
- while (space > 0 && plist != &card->controls) {
- kctl = snd_kcontrol(plist);
- for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) {
- snd_ctl_build_ioff(id, kctl, jidx);
- id++;
- space--;
- list.used++;
- }
- plist = plist->next;
- offset = 0;
- }
- up_read(&card->controls_rwsem);
- if (list.used > 0 &&
- copy_to_user(list.pids, dst,
- list.used * sizeof(struct snd_ctl_elem_id))) {
- vfree(dst);
- return -EFAULT;
- }
- vfree(dst);
- } else {
- down_read(&card->controls_rwsem);
- list.count = card->controls_count;
- up_read(&card->controls_rwsem);
- }
- if (copy_to_user(_list, &list, sizeof(list)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
- struct snd_ctl_elem_info *info)
-{
- struct snd_card *card = ctl->card;
- struct snd_kcontrol *kctl;
- struct snd_kcontrol_volatile *vd;
- unsigned int index_offset;
- int result;
-
- down_read(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, &info->id);
- if (kctl == NULL) {
- up_read(&card->controls_rwsem);
- return -ENOENT;
- }
-#ifdef CONFIG_SND_DEBUG
- info->access = 0;
-#endif
- result = kctl->info(kctl, info);
- if (result >= 0) {
- snd_BUG_ON(info->access);
- index_offset = snd_ctl_get_ioff(kctl, &info->id);
- vd = &kctl->vd[index_offset];
- snd_ctl_build_ioff(&info->id, kctl, index_offset);
- info->access = vd->access;
- if (vd->owner) {
- info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK;
- if (vd->owner == ctl)
- info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER;
- info->owner = pid_vnr(vd->owner->pid);
- } else {
- info->owner = -1;
- }
- }
- up_read(&card->controls_rwsem);
- return result;
-}
-
-static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
- struct snd_ctl_elem_info __user *_info)
-{
- struct snd_ctl_elem_info info;
- int result;
-
- if (copy_from_user(&info, _info, sizeof(info)))
- return -EFAULT;
- snd_power_lock(ctl->card);
- result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
- if (result >= 0)
- result = snd_ctl_elem_info(ctl, &info);
- snd_power_unlock(ctl->card);
- if (result >= 0)
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
- return result;
-}
-
-static int snd_ctl_elem_read(struct snd_card *card,
- struct snd_ctl_elem_value *control)
-{
- struct snd_kcontrol *kctl;
- struct snd_kcontrol_volatile *vd;
- unsigned int index_offset;
- int result;
-
- down_read(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, &control->id);
- if (kctl == NULL) {
- result = -ENOENT;
- } else {
- index_offset = snd_ctl_get_ioff(kctl, &control->id);
- vd = &kctl->vd[index_offset];
- if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) &&
- kctl->get != NULL) {
- snd_ctl_build_ioff(&control->id, kctl, index_offset);
- result = kctl->get(kctl, control);
- } else
- result = -EPERM;
- }
- up_read(&card->controls_rwsem);
- return result;
-}
-
-static int snd_ctl_elem_read_user(struct snd_card *card,
- struct snd_ctl_elem_value __user *_control)
-{
- struct snd_ctl_elem_value *control;
- int result;
-
- control = memdup_user(_control, sizeof(*control));
- if (IS_ERR(control))
- return PTR_ERR(control);
-
- snd_power_lock(card);
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (result >= 0)
- result = snd_ctl_elem_read(card, control);
- snd_power_unlock(card);
- if (result >= 0)
- if (copy_to_user(_control, control, sizeof(*control)))
- result = -EFAULT;
- kfree(control);
- return result;
-}
-
-static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
- struct snd_ctl_elem_value *control)
-{
- struct snd_kcontrol *kctl;
- struct snd_kcontrol_volatile *vd;
- unsigned int index_offset;
- int result;
-
- down_read(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, &control->id);
- if (kctl == NULL) {
- result = -ENOENT;
- } else {
- index_offset = snd_ctl_get_ioff(kctl, &control->id);
- vd = &kctl->vd[index_offset];
- if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ||
- kctl->put == NULL ||
- (file && vd->owner && vd->owner != file)) {
- result = -EPERM;
- } else {
- snd_ctl_build_ioff(&control->id, kctl, index_offset);
- result = kctl->put(kctl, control);
- }
- if (result > 0) {
- up_read(&card->controls_rwsem);
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &control->id);
- return 0;
- }
- }
- up_read(&card->controls_rwsem);
- return result;
-}
-
-static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
- struct snd_ctl_elem_value __user *_control)
-{
- struct snd_ctl_elem_value *control;
- struct snd_card *card;
- int result;
-
- control = memdup_user(_control, sizeof(*control));
- if (IS_ERR(control))
- return PTR_ERR(control);
-
- card = file->card;
- snd_power_lock(card);
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (result >= 0)
- result = snd_ctl_elem_write(card, file, control);
- snd_power_unlock(card);
- if (result >= 0)
- if (copy_to_user(_control, control, sizeof(*control)))
- result = -EFAULT;
- kfree(control);
- return result;
-}
-
-static int snd_ctl_elem_lock(struct snd_ctl_file *file,
- struct snd_ctl_elem_id __user *_id)
-{
- struct snd_card *card = file->card;
- struct snd_ctl_elem_id id;
- struct snd_kcontrol *kctl;
- struct snd_kcontrol_volatile *vd;
- int result;
-
- if (copy_from_user(&id, _id, sizeof(id)))
- return -EFAULT;
- down_write(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, &id);
- if (kctl == NULL) {
- result = -ENOENT;
- } else {
- vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
- if (vd->owner != NULL)
- result = -EBUSY;
- else {
- vd->owner = file;
- result = 0;
- }
- }
- up_write(&card->controls_rwsem);
- return result;
-}
-
-static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
- struct snd_ctl_elem_id __user *_id)
-{
- struct snd_card *card = file->card;
- struct snd_ctl_elem_id id;
- struct snd_kcontrol *kctl;
- struct snd_kcontrol_volatile *vd;
- int result;
-
- if (copy_from_user(&id, _id, sizeof(id)))
- return -EFAULT;
- down_write(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, &id);
- if (kctl == NULL) {
- result = -ENOENT;
- } else {
- vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
- if (vd->owner == NULL)
- result = -EINVAL;
- else if (vd->owner != file)
- result = -EPERM;
- else {
- vd->owner = NULL;
- result = 0;
- }
- }
- up_write(&card->controls_rwsem);
- return result;
-}
-
-struct user_element {
- struct snd_ctl_elem_info info;
- void *elem_data; /* element data */
- unsigned long elem_data_size; /* size of element data in bytes */
- void *tlv_data; /* TLV data */
- unsigned long tlv_data_size; /* TLV data size */
- void *priv_data; /* private data (like strings for enumerated type) */
-};
-
-static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct user_element *ue = kcontrol->private_data;
-
- *uinfo = ue->info;
- return 0;
-}
-
-static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct user_element *ue = kcontrol->private_data;
- const char *names;
- unsigned int item;
-
- item = uinfo->value.enumerated.item;
-
- *uinfo = ue->info;
-
- item = min(item, uinfo->value.enumerated.items - 1);
- uinfo->value.enumerated.item = item;
-
- names = ue->priv_data;
- for (; item > 0; --item)
- names += strlen(names) + 1;
- strcpy(uinfo->value.enumerated.name, names);
-
- return 0;
-}
-
-static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct user_element *ue = kcontrol->private_data;
-
- memcpy(&ucontrol->value, ue->elem_data, ue->elem_data_size);
- return 0;
-}
-
-static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int change;
- struct user_element *ue = kcontrol->private_data;
-
- change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size) != 0;
- if (change)
- memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size);
- return change;
-}
-
-static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
- int op_flag,
- unsigned int size,
- unsigned int __user *tlv)
-{
- struct user_element *ue = kcontrol->private_data;
- int change = 0;
- void *new_data;
-
- if (op_flag > 0) {
- if (size > 1024 * 128) /* sane value */
- return -EINVAL;
-
- new_data = memdup_user(tlv, size);
- if (IS_ERR(new_data))
- return PTR_ERR(new_data);
- change = ue->tlv_data_size != size;
- if (!change)
- change = memcmp(ue->tlv_data, new_data, size);
- kfree(ue->tlv_data);
- ue->tlv_data = new_data;
- ue->tlv_data_size = size;
- } else {
- if (! ue->tlv_data_size || ! ue->tlv_data)
- return -ENXIO;
- if (size < ue->tlv_data_size)
- return -ENOSPC;
- if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
- return -EFAULT;
- }
- return change;
-}
-
-static int snd_ctl_elem_init_enum_names(struct user_element *ue)
-{
- char *names, *p;
- size_t buf_len, name_len;
- unsigned int i;
- const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr;
-
- if (ue->info.value.enumerated.names_length > 64 * 1024)
- return -EINVAL;
-
- names = memdup_user((const void __user *)user_ptrval,
- ue->info.value.enumerated.names_length);
- if (IS_ERR(names))
- return PTR_ERR(names);
-
- /* check that there are enough valid names */
- buf_len = ue->info.value.enumerated.names_length;
- p = names;
- for (i = 0; i < ue->info.value.enumerated.items; ++i) {
- name_len = strnlen(p, buf_len);
- if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
- kfree(names);
- return -EINVAL;
- }
- p += name_len + 1;
- buf_len -= name_len + 1;
- }
-
- ue->priv_data = names;
- ue->info.value.enumerated.names_ptr = 0;
-
- return 0;
-}
-
-static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
-{
- struct user_element *ue = kcontrol->private_data;
-
- kfree(ue->tlv_data);
- kfree(ue->priv_data);
- kfree(ue);
-}
-
-static int snd_ctl_elem_add(struct snd_ctl_file *file,
- struct snd_ctl_elem_info *info, int replace)
-{
- struct snd_card *card = file->card;
- struct snd_kcontrol kctl, *_kctl;
- unsigned int access;
- long private_size;
- struct user_element *ue;
- int idx, err;
-
- if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS)
- return -ENOMEM;
- if (info->count < 1)
- return -EINVAL;
- access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
- (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
- SNDRV_CTL_ELEM_ACCESS_INACTIVE|
- SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE));
- info->id.numid = 0;
- memset(&kctl, 0, sizeof(kctl));
- down_write(&card->controls_rwsem);
- _kctl = snd_ctl_find_id(card, &info->id);
- err = 0;
- if (_kctl) {
- if (replace)
- err = snd_ctl_remove(card, _kctl);
- else
- err = -EBUSY;
- } else {
- if (replace)
- err = -ENOENT;
- }
- up_write(&card->controls_rwsem);
- if (err < 0)
- return err;
- memcpy(&kctl.id, &info->id, sizeof(info->id));
- kctl.count = info->owner ? info->owner : 1;
- access |= SNDRV_CTL_ELEM_ACCESS_USER;
- if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED)
- kctl.info = snd_ctl_elem_user_enum_info;
- else
- kctl.info = snd_ctl_elem_user_info;
- if (access & SNDRV_CTL_ELEM_ACCESS_READ)
- kctl.get = snd_ctl_elem_user_get;
- if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
- kctl.put = snd_ctl_elem_user_put;
- if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
- kctl.tlv.c = snd_ctl_elem_user_tlv;
- access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
- }
- switch (info->type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- private_size = sizeof(long);
- if (info->count > 128)
- return -EINVAL;
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- private_size = sizeof(long long);
- if (info->count > 64)
- return -EINVAL;
- break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- private_size = sizeof(unsigned int);
- if (info->count > 128 || info->value.enumerated.items == 0)
- return -EINVAL;
- break;
- case SNDRV_CTL_ELEM_TYPE_BYTES:
- private_size = sizeof(unsigned char);
- if (info->count > 512)
- return -EINVAL;
- break;
- case SNDRV_CTL_ELEM_TYPE_IEC958:
- private_size = sizeof(struct snd_aes_iec958);
- if (info->count != 1)
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
- private_size *= info->count;
- ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
- if (ue == NULL)
- return -ENOMEM;
- ue->info = *info;
- ue->info.access = 0;
- ue->elem_data = (char *)ue + sizeof(*ue);
- ue->elem_data_size = private_size;
- if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
- err = snd_ctl_elem_init_enum_names(ue);
- if (err < 0) {
- kfree(ue);
- return err;
- }
- }
- kctl.private_free = snd_ctl_elem_user_free;
- _kctl = snd_ctl_new(&kctl, access);
- if (_kctl == NULL) {
- kfree(ue->priv_data);
- kfree(ue);
- return -ENOMEM;
- }
- _kctl->private_data = ue;
- for (idx = 0; idx < _kctl->count; idx++)
- _kctl->vd[idx].owner = file;
- err = snd_ctl_add(card, _kctl);
- if (err < 0)
- return err;
-
- down_write(&card->controls_rwsem);
- card->user_ctl_count++;
- up_write(&card->controls_rwsem);
-
- return 0;
-}
-
-static int snd_ctl_elem_add_user(struct snd_ctl_file *file,
- struct snd_ctl_elem_info __user *_info, int replace)
-{
- struct snd_ctl_elem_info info;
- if (copy_from_user(&info, _info, sizeof(info)))
- return -EFAULT;
- return snd_ctl_elem_add(file, &info, replace);
-}
-
-static int snd_ctl_elem_remove(struct snd_ctl_file *file,
- struct snd_ctl_elem_id __user *_id)
-{
- struct snd_ctl_elem_id id;
-
- if (copy_from_user(&id, _id, sizeof(id)))
- return -EFAULT;
- return snd_ctl_remove_user_ctl(file, &id);
-}
-
-static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
-{
- int subscribe;
- if (get_user(subscribe, ptr))
- return -EFAULT;
- if (subscribe < 0) {
- subscribe = file->subscribed;
- if (put_user(subscribe, ptr))
- return -EFAULT;
- return 0;
- }
- if (subscribe) {
- file->subscribed = 1;
- return 0;
- } else if (file->subscribed) {
- snd_ctl_empty_read_queue(file);
- file->subscribed = 0;
- }
- return 0;
-}
-
-static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
- struct snd_ctl_tlv __user *_tlv,
- int op_flag)
-{
- struct snd_card *card = file->card;
- struct snd_ctl_tlv tlv;
- struct snd_kcontrol *kctl;
- struct snd_kcontrol_volatile *vd;
- unsigned int len;
- int err = 0;
-
- if (copy_from_user(&tlv, _tlv, sizeof(tlv)))
- return -EFAULT;
- if (tlv.length < sizeof(unsigned int) * 2)
- return -EINVAL;
- down_read(&card->controls_rwsem);
- kctl = snd_ctl_find_numid(card, tlv.numid);
- if (kctl == NULL) {
- err = -ENOENT;
- goto __kctl_end;
- }
- if (kctl->tlv.p == NULL) {
- err = -ENXIO;
- goto __kctl_end;
- }
- vd = &kctl->vd[tlv.numid - kctl->id.numid];
- if ((op_flag == 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) == 0) ||
- (op_flag > 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) == 0) ||
- (op_flag < 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) == 0)) {
- err = -ENXIO;
- goto __kctl_end;
- }
- if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
- if (vd->owner != NULL && vd->owner != file) {
- err = -EPERM;
- goto __kctl_end;
- }
- err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
- if (err > 0) {
- up_read(&card->controls_rwsem);
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
- return 0;
- }
- } else {
- if (op_flag) {
- err = -ENXIO;
- goto __kctl_end;
- }
- len = kctl->tlv.p[1] + 2 * sizeof(unsigned int);
- if (tlv.length < len) {
- err = -ENOMEM;
- goto __kctl_end;
- }
- if (copy_to_user(_tlv->tlv, kctl->tlv.p, len))
- err = -EFAULT;
- }
- __kctl_end:
- up_read(&card->controls_rwsem);
- return err;
-}
-
-static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct snd_ctl_file *ctl;
- struct snd_card *card;
- struct snd_kctl_ioctl *p;
- void __user *argp = (void __user *)arg;
- int __user *ip = argp;
- int err;
-
- ctl = file->private_data;
- card = ctl->card;
- if (snd_BUG_ON(!card))
- return -ENXIO;
- switch (cmd) {
- case SNDRV_CTL_IOCTL_PVERSION:
- return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0;
- case SNDRV_CTL_IOCTL_CARD_INFO:
- return snd_ctl_card_info(card, ctl, cmd, argp);
- case SNDRV_CTL_IOCTL_ELEM_LIST:
- return snd_ctl_elem_list(card, argp);
- case SNDRV_CTL_IOCTL_ELEM_INFO:
- return snd_ctl_elem_info_user(ctl, argp);
- case SNDRV_CTL_IOCTL_ELEM_READ:
- return snd_ctl_elem_read_user(card, argp);
- case SNDRV_CTL_IOCTL_ELEM_WRITE:
- return snd_ctl_elem_write_user(ctl, argp);
- case SNDRV_CTL_IOCTL_ELEM_LOCK:
- return snd_ctl_elem_lock(ctl, argp);
- case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
- return snd_ctl_elem_unlock(ctl, argp);
- case SNDRV_CTL_IOCTL_ELEM_ADD:
- return snd_ctl_elem_add_user(ctl, argp, 0);
- case SNDRV_CTL_IOCTL_ELEM_REPLACE:
- return snd_ctl_elem_add_user(ctl, argp, 1);
- case SNDRV_CTL_IOCTL_ELEM_REMOVE:
- return snd_ctl_elem_remove(ctl, argp);
- case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
- return snd_ctl_subscribe_events(ctl, ip);
- case SNDRV_CTL_IOCTL_TLV_READ:
- return snd_ctl_tlv_ioctl(ctl, argp, 0);
- case SNDRV_CTL_IOCTL_TLV_WRITE:
- return snd_ctl_tlv_ioctl(ctl, argp, 1);
- case SNDRV_CTL_IOCTL_TLV_COMMAND:
- return snd_ctl_tlv_ioctl(ctl, argp, -1);
- case SNDRV_CTL_IOCTL_POWER:
- return -ENOPROTOOPT;
- case SNDRV_CTL_IOCTL_POWER_STATE:
-#ifdef CONFIG_PM
- return put_user(card->power_state, ip) ? -EFAULT : 0;
-#else
- return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0;
-#endif
- }
- down_read(&snd_ioctl_rwsem);
- list_for_each_entry(p, &snd_control_ioctls, list) {
- err = p->fioctl(card, ctl, cmd, arg);
- if (err != -ENOIOCTLCMD) {
- up_read(&snd_ioctl_rwsem);
- return err;
- }
- }
- up_read(&snd_ioctl_rwsem);
- snd_printdd("unknown ioctl = 0x%x\n", cmd);
- return -ENOTTY;
-}
-
-static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
- size_t count, loff_t * offset)
-{
- struct snd_ctl_file *ctl;
- int err = 0;
- ssize_t result = 0;
-
- ctl = file->private_data;
- if (snd_BUG_ON(!ctl || !ctl->card))
- return -ENXIO;
- if (!ctl->subscribed)
- return -EBADFD;
- if (count < sizeof(struct snd_ctl_event))
- return -EINVAL;
- spin_lock_irq(&ctl->read_lock);
- while (count >= sizeof(struct snd_ctl_event)) {
- struct snd_ctl_event ev;
- struct snd_kctl_event *kev;
- while (list_empty(&ctl->events)) {
- wait_queue_t wait;
- if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
- err = -EAGAIN;
- goto __end_lock;
- }
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&ctl->change_sleep, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&ctl->read_lock);
- schedule();
- remove_wait_queue(&ctl->change_sleep, &wait);
- if (ctl->card->shutdown)
- return -ENODEV;
- if (signal_pending(current))
- return -ERESTARTSYS;
- spin_lock_irq(&ctl->read_lock);
- }
- kev = snd_kctl_event(ctl->events.next);
- ev.type = SNDRV_CTL_EVENT_ELEM;
- ev.data.elem.mask = kev->mask;
- ev.data.elem.id = kev->id;
- list_del(&kev->list);
- spin_unlock_irq(&ctl->read_lock);
- kfree(kev);
- if (copy_to_user(buffer, &ev, sizeof(struct snd_ctl_event))) {
- err = -EFAULT;
- goto __end;
- }
- spin_lock_irq(&ctl->read_lock);
- buffer += sizeof(struct snd_ctl_event);
- count -= sizeof(struct snd_ctl_event);
- result += sizeof(struct snd_ctl_event);
- }
- __end_lock:
- spin_unlock_irq(&ctl->read_lock);
- __end:
- return result > 0 ? result : err;
-}
-
-static unsigned int snd_ctl_poll(struct file *file, poll_table * wait)
-{
- unsigned int mask;
- struct snd_ctl_file *ctl;
-
- ctl = file->private_data;
- if (!ctl->subscribed)
- return 0;
- poll_wait(file, &ctl->change_sleep, wait);
-
- mask = 0;
- if (!list_empty(&ctl->events))
- mask |= POLLIN | POLLRDNORM;
-
- return mask;
-}
-
-/*
- * register the device-specific control-ioctls.
- * called from each device manager like pcm.c, hwdep.c, etc.
- */
-static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists)
-{
- struct snd_kctl_ioctl *pn;
-
- pn = kzalloc(sizeof(struct snd_kctl_ioctl), GFP_KERNEL);
- if (pn == NULL)
- return -ENOMEM;
- pn->fioctl = fcn;
- down_write(&snd_ioctl_rwsem);
- list_add_tail(&pn->list, lists);
- up_write(&snd_ioctl_rwsem);
- return 0;
-}
-
-int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
-{
- return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls);
-}
-
-EXPORT_SYMBOL(snd_ctl_register_ioctl);
-
-#ifdef CONFIG_COMPAT
-int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn)
-{
- return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls);
-}
-
-EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
-#endif
-
-/*
- * de-register the device-specific control-ioctls.
- */
-static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn,
- struct list_head *lists)
-{
- struct snd_kctl_ioctl *p;
-
- if (snd_BUG_ON(!fcn))
- return -EINVAL;
- down_write(&snd_ioctl_rwsem);
- list_for_each_entry(p, lists, list) {
- if (p->fioctl == fcn) {
- list_del(&p->list);
- up_write(&snd_ioctl_rwsem);
- kfree(p);
- return 0;
- }
- }
- up_write(&snd_ioctl_rwsem);
- snd_BUG();
- return -EINVAL;
-}
-
-int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
-{
- return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls);
-}
-
-EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
-
-#ifdef CONFIG_COMPAT
-int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
-{
- return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls);
-}
-
-EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
-#endif
-
-static int snd_ctl_fasync(int fd, struct file * file, int on)
-{
- struct snd_ctl_file *ctl;
-
- ctl = file->private_data;
- return fasync_helper(fd, file, on, &ctl->fasync);
-}
-
-/*
- * ioctl32 compat
- */
-#ifdef CONFIG_COMPAT
-#include "control_compat.c"
-#else
-#define snd_ctl_ioctl_compat NULL
-#endif
-
-/*
- * INIT PART
- */
-
-static const struct file_operations snd_ctl_f_ops =
-{
- .owner = THIS_MODULE,
- .read = snd_ctl_read,
- .open = snd_ctl_open,
- .release = snd_ctl_release,
- .llseek = no_llseek,
- .poll = snd_ctl_poll,
- .unlocked_ioctl = snd_ctl_ioctl,
- .compat_ioctl = snd_ctl_ioctl_compat,
- .fasync = snd_ctl_fasync,
-};
-
-/*
- * registration of the control device
- */
-static int snd_ctl_dev_register(struct snd_device *device)
-{
- struct snd_card *card = device->device_data;
- int err, cardnum;
- char name[16];
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- cardnum = card->number;
- if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS))
- return -ENXIO;
- sprintf(name, "controlC%i", cardnum);
- if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
- &snd_ctl_f_ops, card, name)) < 0)
- return err;
- return 0;
-}
-
-/*
- * disconnection of the control device
- */
-static int snd_ctl_dev_disconnect(struct snd_device *device)
-{
- struct snd_card *card = device->device_data;
- struct snd_ctl_file *ctl;
- int err, cardnum;
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- cardnum = card->number;
- if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS))
- return -ENXIO;
-
- read_lock(&card->ctl_files_rwlock);
- list_for_each_entry(ctl, &card->ctl_files, list) {
- wake_up(&ctl->change_sleep);
- kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
- }
- read_unlock(&card->ctl_files_rwlock);
-
- if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL,
- card, -1)) < 0)
- return err;
- return 0;
-}
-
-/*
- * free all controls
- */
-static int snd_ctl_dev_free(struct snd_device *device)
-{
- struct snd_card *card = device->device_data;
- struct snd_kcontrol *control;
-
- down_write(&card->controls_rwsem);
- while (!list_empty(&card->controls)) {
- control = snd_kcontrol(card->controls.next);
- snd_ctl_remove(card, control);
- }
- up_write(&card->controls_rwsem);
- return 0;
-}
-
-/*
- * create control core:
- * called from init.c
- */
-int snd_ctl_create(struct snd_card *card)
-{
- static struct snd_device_ops ops = {
- .dev_free = snd_ctl_dev_free,
- .dev_register = snd_ctl_dev_register,
- .dev_disconnect = snd_ctl_dev_disconnect,
- };
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
-}
-
-/*
- * Frequently used control callbacks/helpers
- */
-int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_ctl_boolean_mono_info);
-
-int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_ctl_boolean_stereo_info);
-
-/**
- * snd_ctl_enum_info - fills the info structure for an enumerated control
- * @info: the structure to be filled
- * @channels: the number of the control's channels; often one
- * @items: the number of control values; also the size of @names
- * @names: an array containing the names of all control values
- *
- * Sets all required fields in @info to their appropriate values.
- * If the control's accessibility is not the default (readable and writable),
- * the caller has to fill @info->access.
- */
-int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
- unsigned int items, const char *const names[])
-{
- info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- info->count = channels;
- info->value.enumerated.items = items;
- if (info->value.enumerated.item >= items)
- info->value.enumerated.item = items - 1;
- strlcpy(info->value.enumerated.name,
- names[info->value.enumerated.item],
- sizeof(info->value.enumerated.name));
- return 0;
-}
-EXPORT_SYMBOL(snd_ctl_enum_info);
diff --git a/ANDROID_3.4.5/sound/core/control_compat.c b/ANDROID_3.4.5/sound/core/control_compat.c
deleted file mode 100644
index 2bb95a7a..00000000
--- a/ANDROID_3.4.5/sound/core/control_compat.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * compat ioctls for control API
- *
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* this file included from control.c */
-
-#include <linux/compat.h>
-#include <linux/slab.h>
-
-struct snd_ctl_elem_list32 {
- u32 offset;
- u32 space;
- u32 used;
- u32 count;
- u32 pids;
- unsigned char reserved[50];
-} /* don't set packed attribute here */;
-
-static int snd_ctl_elem_list_compat(struct snd_card *card,
- struct snd_ctl_elem_list32 __user *data32)
-{
- struct snd_ctl_elem_list __user *data;
- compat_caddr_t ptr;
- int err;
-
- data = compat_alloc_user_space(sizeof(*data));
-
- /* offset, space, used, count */
- if (copy_in_user(data, data32, 4 * sizeof(u32)))
- return -EFAULT;
- /* pids */
- if (get_user(ptr, &data32->pids) ||
- put_user(compat_ptr(ptr), &data->pids))
- return -EFAULT;
- err = snd_ctl_elem_list(card, data);
- if (err < 0)
- return err;
- /* copy the result */
- if (copy_in_user(data32, data, 4 * sizeof(u32)))
- return -EFAULT;
- return 0;
-}
-
-/*
- * control element info
- * it uses union, so the things are not easy..
- */
-
-struct snd_ctl_elem_info32 {
- struct snd_ctl_elem_id id; // the size of struct is same
- s32 type;
- u32 access;
- u32 count;
- s32 owner;
- union {
- struct {
- s32 min;
- s32 max;
- s32 step;
- } integer;
- struct {
- u64 min;
- u64 max;
- u64 step;
- } integer64;
- struct {
- u32 items;
- u32 item;
- char name[64];
- u64 names_ptr;
- u32 names_length;
- } enumerated;
- unsigned char reserved[128];
- } value;
- unsigned char reserved[64];
-} __attribute__((packed));
-
-static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
- struct snd_ctl_elem_info32 __user *data32)
-{
- struct snd_ctl_elem_info *data;
- int err;
-
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (! data)
- return -ENOMEM;
-
- err = -EFAULT;
- /* copy id */
- if (copy_from_user(&data->id, &data32->id, sizeof(data->id)))
- goto error;
- /* we need to copy the item index.
- * hope this doesn't break anything..
- */
- if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
- goto error;
-
- snd_power_lock(ctl->card);
- err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
- if (err >= 0)
- err = snd_ctl_elem_info(ctl, data);
- snd_power_unlock(ctl->card);
-
- if (err < 0)
- goto error;
- /* restore info to 32bit */
- err = -EFAULT;
- /* id, type, access, count */
- if (copy_to_user(&data32->id, &data->id, sizeof(data->id)) ||
- copy_to_user(&data32->type, &data->type, 3 * sizeof(u32)))
- goto error;
- if (put_user(data->owner, &data32->owner))
- goto error;
- switch (data->type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- if (put_user(data->value.integer.min, &data32->value.integer.min) ||
- put_user(data->value.integer.max, &data32->value.integer.max) ||
- put_user(data->value.integer.step, &data32->value.integer.step))
- goto error;
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- if (copy_to_user(&data32->value.integer64,
- &data->value.integer64,
- sizeof(data->value.integer64)))
- goto error;
- break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- if (copy_to_user(&data32->value.enumerated,
- &data->value.enumerated,
- sizeof(data->value.enumerated)))
- goto error;
- break;
- default:
- break;
- }
- err = 0;
- error:
- kfree(data);
- return err;
-}
-
-/* read / write */
-struct snd_ctl_elem_value32 {
- struct snd_ctl_elem_id id;
- unsigned int indirect; /* bit-field causes misalignment */
- union {
- s32 integer[128];
- unsigned char data[512];
-#ifndef CONFIG_X86_64
- s64 integer64[64];
-#endif
- } value;
- unsigned char reserved[128];
-};
-
-
-/* get the value type and count of the control */
-static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
- int *countp)
-{
- struct snd_kcontrol *kctl;
- struct snd_ctl_elem_info *info;
- int err;
-
- down_read(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, id);
- if (! kctl) {
- up_read(&card->controls_rwsem);
- return -ENXIO;
- }
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (info == NULL) {
- up_read(&card->controls_rwsem);
- return -ENOMEM;
- }
- info->id = *id;
- err = kctl->info(kctl, info);
- up_read(&card->controls_rwsem);
- if (err >= 0) {
- err = info->type;
- *countp = info->count;
- }
- kfree(info);
- return err;
-}
-
-static int get_elem_size(int type, int count)
-{
- switch (type) {
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- return sizeof(s64) * count;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- return sizeof(int) * count;
- case SNDRV_CTL_ELEM_TYPE_BYTES:
- return 512;
- case SNDRV_CTL_ELEM_TYPE_IEC958:
- return sizeof(struct snd_aes_iec958);
- default:
- return -1;
- }
-}
-
-static int copy_ctl_value_from_user(struct snd_card *card,
- struct snd_ctl_elem_value *data,
- struct snd_ctl_elem_value32 __user *data32,
- int *typep, int *countp)
-{
- int i, type, size;
- int uninitialized_var(count);
- unsigned int indirect;
-
- if (copy_from_user(&data->id, &data32->id, sizeof(data->id)))
- return -EFAULT;
- if (get_user(indirect, &data32->indirect))
- return -EFAULT;
- if (indirect)
- return -EINVAL;
- type = get_ctl_type(card, &data->id, &count);
- if (type < 0)
- return type;
-
- if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
- type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
- for (i = 0; i < count; i++) {
- int val;
- if (get_user(val, &data32->value.integer[i]))
- return -EFAULT;
- data->value.integer.value[i] = val;
- }
- } else {
- size = get_elem_size(type, count);
- if (size < 0) {
- printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
- return -EINVAL;
- }
- if (copy_from_user(data->value.bytes.data,
- data32->value.data, size))
- return -EFAULT;
- }
-
- *typep = type;
- *countp = count;
- return 0;
-}
-
-/* restore the value to 32bit */
-static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
- struct snd_ctl_elem_value *data,
- int type, int count)
-{
- int i, size;
-
- if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
- type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
- for (i = 0; i < count; i++) {
- int val;
- val = data->value.integer.value[i];
- if (put_user(val, &data32->value.integer[i]))
- return -EFAULT;
- }
- } else {
- size = get_elem_size(type, count);
- if (copy_to_user(data32->value.data,
- data->value.bytes.data, size))
- return -EFAULT;
- }
- return 0;
-}
-
-static int snd_ctl_elem_read_user_compat(struct snd_card *card,
- struct snd_ctl_elem_value32 __user *data32)
-{
- struct snd_ctl_elem_value *data;
- int err, type, count;
-
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
- goto error;
-
- snd_power_lock(card);
- err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (err >= 0)
- err = snd_ctl_elem_read(card, data);
- snd_power_unlock(card);
- if (err >= 0)
- err = copy_ctl_value_to_user(data32, data, type, count);
- error:
- kfree(data);
- return err;
-}
-
-static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
- struct snd_ctl_elem_value32 __user *data32)
-{
- struct snd_ctl_elem_value *data;
- struct snd_card *card = file->card;
- int err, type, count;
-
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
- goto error;
-
- snd_power_lock(card);
- err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (err >= 0)
- err = snd_ctl_elem_write(card, file, data);
- snd_power_unlock(card);
- if (err >= 0)
- err = copy_ctl_value_to_user(data32, data, type, count);
- error:
- kfree(data);
- return err;
-}
-
-/* add or replace a user control */
-static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
- struct snd_ctl_elem_info32 __user *data32,
- int replace)
-{
- struct snd_ctl_elem_info *data;
- int err;
-
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (! data)
- return -ENOMEM;
-
- err = -EFAULT;
- /* id, type, access, count */ \
- if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) ||
- copy_from_user(&data->type, &data32->type, 3 * sizeof(u32)))
- goto error;
- if (get_user(data->owner, &data32->owner) ||
- get_user(data->type, &data32->type))
- goto error;
- switch (data->type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- if (get_user(data->value.integer.min, &data32->value.integer.min) ||
- get_user(data->value.integer.max, &data32->value.integer.max) ||
- get_user(data->value.integer.step, &data32->value.integer.step))
- goto error;
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- if (copy_from_user(&data->value.integer64,
- &data32->value.integer64,
- sizeof(data->value.integer64)))
- goto error;
- break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- if (copy_from_user(&data->value.enumerated,
- &data32->value.enumerated,
- sizeof(data->value.enumerated)))
- goto error;
- data->value.enumerated.names_ptr =
- (uintptr_t)compat_ptr(data->value.enumerated.names_ptr);
- break;
- default:
- break;
- }
- err = snd_ctl_elem_add(file, data, replace);
- error:
- kfree(data);
- return err;
-}
-
-enum {
- SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct snd_ctl_elem_list32),
- SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct snd_ctl_elem_info32),
- SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct snd_ctl_elem_value32),
- SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32),
- SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32),
- SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32),
-};
-
-static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct snd_ctl_file *ctl;
- struct snd_kctl_ioctl *p;
- void __user *argp = compat_ptr(arg);
- int err;
-
- ctl = file->private_data;
- if (snd_BUG_ON(!ctl || !ctl->card))
- return -ENXIO;
-
- switch (cmd) {
- case SNDRV_CTL_IOCTL_PVERSION:
- case SNDRV_CTL_IOCTL_CARD_INFO:
- case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
- case SNDRV_CTL_IOCTL_POWER:
- case SNDRV_CTL_IOCTL_POWER_STATE:
- case SNDRV_CTL_IOCTL_ELEM_LOCK:
- case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
- case SNDRV_CTL_IOCTL_ELEM_REMOVE:
- case SNDRV_CTL_IOCTL_TLV_READ:
- case SNDRV_CTL_IOCTL_TLV_WRITE:
- case SNDRV_CTL_IOCTL_TLV_COMMAND:
- return snd_ctl_ioctl(file, cmd, (unsigned long)argp);
- case SNDRV_CTL_IOCTL_ELEM_LIST32:
- return snd_ctl_elem_list_compat(ctl->card, argp);
- case SNDRV_CTL_IOCTL_ELEM_INFO32:
- return snd_ctl_elem_info_compat(ctl, argp);
- case SNDRV_CTL_IOCTL_ELEM_READ32:
- return snd_ctl_elem_read_user_compat(ctl->card, argp);
- case SNDRV_CTL_IOCTL_ELEM_WRITE32:
- return snd_ctl_elem_write_user_compat(ctl, argp);
- case SNDRV_CTL_IOCTL_ELEM_ADD32:
- return snd_ctl_elem_add_compat(ctl, argp, 0);
- case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
- return snd_ctl_elem_add_compat(ctl, argp, 1);
- }
-
- down_read(&snd_ioctl_rwsem);
- list_for_each_entry(p, &snd_control_compat_ioctls, list) {
- if (p->fioctl) {
- err = p->fioctl(ctl->card, ctl, cmd, arg);
- if (err != -ENOIOCTLCMD) {
- up_read(&snd_ioctl_rwsem);
- return err;
- }
- }
- }
- up_read(&snd_ioctl_rwsem);
- return -ENOIOCTLCMD;
-}
diff --git a/ANDROID_3.4.5/sound/core/ctljack.c b/ANDROID_3.4.5/sound/core/ctljack.c
deleted file mode 100644
index e4b38fbe..00000000
--- a/ANDROID_3.4.5/sound/core/ctljack.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Helper functions for jack-detection kcontrols
- *
- * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/control.h>
-
-#define jack_detect_kctl_info snd_ctl_boolean_mono_info
-
-static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.integer.value[0] = kcontrol->private_value;
- return 0;
-}
-
-static struct snd_kcontrol_new jack_detect_kctl = {
- /* name is filled later */
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .access = SNDRV_CTL_ELEM_ACCESS_READ,
- .info = jack_detect_kctl_info,
- .get = jack_detect_kctl_get,
-};
-
-struct snd_kcontrol *
-snd_kctl_jack_new(const char *name, int idx, void *private_data)
-{
- struct snd_kcontrol *kctl;
- kctl = snd_ctl_new1(&jack_detect_kctl, private_data);
- if (!kctl)
- return NULL;
- snprintf(kctl->id.name, sizeof(kctl->id.name), "%s Jack", name);
- kctl->id.index = idx;
- kctl->private_value = 0;
- return kctl;
-}
-EXPORT_SYMBOL_GPL(snd_kctl_jack_new);
-
-void snd_kctl_jack_report(struct snd_card *card,
- struct snd_kcontrol *kctl, bool status)
-{
- if (kctl->private_value == status)
- return;
- kctl->private_value = status;
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
-}
-EXPORT_SYMBOL_GPL(snd_kctl_jack_report);
diff --git a/ANDROID_3.4.5/sound/core/device.c b/ANDROID_3.4.5/sound/core/device.c
deleted file mode 100644
index f03cb544..00000000
--- a/ANDROID_3.4.5/sound/core/device.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Device management routines
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/export.h>
-#include <linux/errno.h>
-#include <sound/core.h>
-
-/**
- * snd_device_new - create an ALSA device component
- * @card: the card instance
- * @type: the device type, SNDRV_DEV_XXX
- * @device_data: the data pointer of this device
- * @ops: the operator table
- *
- * Creates a new device component for the given data pointer.
- * The device will be assigned to the card and managed together
- * by the card.
- *
- * The data pointer plays a role as the identifier, too, so the
- * pointer address must be unique and unchanged.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_device_new(struct snd_card *card, snd_device_type_t type,
- void *device_data, struct snd_device_ops *ops)
-{
- struct snd_device *dev;
-
- if (snd_BUG_ON(!card || !device_data || !ops))
- return -ENXIO;
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
- snd_printk(KERN_ERR "Cannot allocate device\n");
- return -ENOMEM;
- }
- dev->card = card;
- dev->type = type;
- dev->state = SNDRV_DEV_BUILD;
- dev->device_data = device_data;
- dev->ops = ops;
- list_add(&dev->list, &card->devices); /* add to the head of list */
- return 0;
-}
-
-EXPORT_SYMBOL(snd_device_new);
-
-/**
- * snd_device_free - release the device from the card
- * @card: the card instance
- * @device_data: the data pointer to release
- *
- * Removes the device from the list on the card and invokes the
- * callbacks, dev_disconnect and dev_free, corresponding to the state.
- * Then release the device.
- *
- * Returns zero if successful, or a negative error code on failure or if the
- * device not found.
- */
-int snd_device_free(struct snd_card *card, void *device_data)
-{
- struct snd_device *dev;
-
- if (snd_BUG_ON(!card || !device_data))
- return -ENXIO;
- list_for_each_entry(dev, &card->devices, list) {
- if (dev->device_data != device_data)
- continue;
- /* unlink */
- list_del(&dev->list);
- if (dev->state == SNDRV_DEV_REGISTERED &&
- dev->ops->dev_disconnect)
- if (dev->ops->dev_disconnect(dev))
- snd_printk(KERN_ERR
- "device disconnect failure\n");
- if (dev->ops->dev_free) {
- if (dev->ops->dev_free(dev))
- snd_printk(KERN_ERR "device free failure\n");
- }
- kfree(dev);
- return 0;
- }
- snd_printd("device free %p (from %pF), not found\n", device_data,
- __builtin_return_address(0));
- return -ENXIO;
-}
-
-EXPORT_SYMBOL(snd_device_free);
-
-/**
- * snd_device_disconnect - disconnect the device
- * @card: the card instance
- * @device_data: the data pointer to disconnect
- *
- * Turns the device into the disconnection state, invoking
- * dev_disconnect callback, if the device was already registered.
- *
- * Usually called from snd_card_disconnect().
- *
- * Returns zero if successful, or a negative error code on failure or if the
- * device not found.
- */
-int snd_device_disconnect(struct snd_card *card, void *device_data)
-{
- struct snd_device *dev;
-
- if (snd_BUG_ON(!card || !device_data))
- return -ENXIO;
- list_for_each_entry(dev, &card->devices, list) {
- if (dev->device_data != device_data)
- continue;
- if (dev->state == SNDRV_DEV_REGISTERED &&
- dev->ops->dev_disconnect) {
- if (dev->ops->dev_disconnect(dev))
- snd_printk(KERN_ERR "device disconnect failure\n");
- dev->state = SNDRV_DEV_DISCONNECTED;
- }
- return 0;
- }
- snd_printd("device disconnect %p (from %pF), not found\n", device_data,
- __builtin_return_address(0));
- return -ENXIO;
-}
-
-/**
- * snd_device_register - register the device
- * @card: the card instance
- * @device_data: the data pointer to register
- *
- * Registers the device which was already created via
- * snd_device_new(). Usually this is called from snd_card_register(),
- * but it can be called later if any new devices are created after
- * invocation of snd_card_register().
- *
- * Returns zero if successful, or a negative error code on failure or if the
- * device not found.
- */
-int snd_device_register(struct snd_card *card, void *device_data)
-{
- struct snd_device *dev;
- int err;
-
- if (snd_BUG_ON(!card || !device_data))
- return -ENXIO;
- list_for_each_entry(dev, &card->devices, list) {
- if (dev->device_data != device_data)
- continue;
- if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
- if ((err = dev->ops->dev_register(dev)) < 0)
- return err;
- dev->state = SNDRV_DEV_REGISTERED;
- return 0;
- }
- snd_printd("snd_device_register busy\n");
- return -EBUSY;
- }
- snd_BUG();
- return -ENXIO;
-}
-
-EXPORT_SYMBOL(snd_device_register);
-
-/*
- * register all the devices on the card.
- * called from init.c
- */
-int snd_device_register_all(struct snd_card *card)
-{
- struct snd_device *dev;
- int err;
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- list_for_each_entry(dev, &card->devices, list) {
- if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
- if ((err = dev->ops->dev_register(dev)) < 0)
- return err;
- dev->state = SNDRV_DEV_REGISTERED;
- }
- }
- return 0;
-}
-
-/*
- * disconnect all the devices on the card.
- * called from init.c
- */
-int snd_device_disconnect_all(struct snd_card *card)
-{
- struct snd_device *dev;
- int err = 0;
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- list_for_each_entry(dev, &card->devices, list) {
- if (snd_device_disconnect(card, dev->device_data) < 0)
- err = -ENXIO;
- }
- return err;
-}
-
-/*
- * release all the devices on the card.
- * called from init.c
- */
-int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd)
-{
- struct snd_device *dev;
- int err;
- unsigned int range_low, range_high, type;
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- range_low = (__force unsigned int)cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
- range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1;
- __again:
- list_for_each_entry(dev, &card->devices, list) {
- type = (__force unsigned int)dev->type;
- if (type >= range_low && type <= range_high) {
- if ((err = snd_device_free(card, dev->device_data)) < 0)
- return err;
- goto __again;
- }
- }
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/hrtimer.c b/ANDROID_3.4.5/sound/core/hrtimer.c
deleted file mode 100644
index b8b31c43..00000000
--- a/ANDROID_3.4.5/sound/core/hrtimer.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * ALSA timer back-end using hrtimer
- * Copyright (C) 2008 Takashi Iwai
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/hrtimer.h>
-#include <sound/core.h>
-#include <sound/timer.h>
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("ALSA hrtimer backend");
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_HRTIMER));
-
-#define NANO_SEC 1000000000UL /* 10^9 in sec */
-static unsigned int resolution;
-
-struct snd_hrtimer {
- struct snd_timer *timer;
- struct hrtimer hrt;
- atomic_t running;
-};
-
-static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
-{
- struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt);
- struct snd_timer *t = stime->timer;
- unsigned long oruns;
-
- if (!atomic_read(&stime->running))
- return HRTIMER_NORESTART;
-
- oruns = hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution));
- snd_timer_interrupt(stime->timer, t->sticks * oruns);
-
- if (!atomic_read(&stime->running))
- return HRTIMER_NORESTART;
- return HRTIMER_RESTART;
-}
-
-static int snd_hrtimer_open(struct snd_timer *t)
-{
- struct snd_hrtimer *stime;
-
- stime = kmalloc(sizeof(*stime), GFP_KERNEL);
- if (!stime)
- return -ENOMEM;
- hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- stime->timer = t;
- stime->hrt.function = snd_hrtimer_callback;
- atomic_set(&stime->running, 0);
- t->private_data = stime;
- return 0;
-}
-
-static int snd_hrtimer_close(struct snd_timer *t)
-{
- struct snd_hrtimer *stime = t->private_data;
-
- if (stime) {
- hrtimer_cancel(&stime->hrt);
- kfree(stime);
- t->private_data = NULL;
- }
- return 0;
-}
-
-static int snd_hrtimer_start(struct snd_timer *t)
-{
- struct snd_hrtimer *stime = t->private_data;
-
- atomic_set(&stime->running, 0);
- hrtimer_cancel(&stime->hrt);
- hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
- HRTIMER_MODE_REL);
- atomic_set(&stime->running, 1);
- return 0;
-}
-
-static int snd_hrtimer_stop(struct snd_timer *t)
-{
- struct snd_hrtimer *stime = t->private_data;
- atomic_set(&stime->running, 0);
- return 0;
-}
-
-static struct snd_timer_hardware hrtimer_hw = {
- .flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_TASKLET,
- .open = snd_hrtimer_open,
- .close = snd_hrtimer_close,
- .start = snd_hrtimer_start,
- .stop = snd_hrtimer_stop,
-};
-
-/*
- * entry functions
- */
-
-static struct snd_timer *mytimer;
-
-static int __init snd_hrtimer_init(void)
-{
- struct snd_timer *timer;
- struct timespec tp;
- int err;
-
- hrtimer_get_res(CLOCK_MONOTONIC, &tp);
- if (tp.tv_sec > 0 || !tp.tv_nsec) {
- snd_printk(KERN_ERR
- "snd-hrtimer: Invalid resolution %u.%09u",
- (unsigned)tp.tv_sec, (unsigned)tp.tv_nsec);
- return -EINVAL;
- }
- resolution = tp.tv_nsec;
-
- /* Create a new timer and set up the fields */
- err = snd_timer_global_new("hrtimer", SNDRV_TIMER_GLOBAL_HRTIMER,
- &timer);
- if (err < 0)
- return err;
-
- timer->module = THIS_MODULE;
- strcpy(timer->name, "HR timer");
- timer->hw = hrtimer_hw;
- timer->hw.resolution = resolution;
- timer->hw.ticks = NANO_SEC / resolution;
-
- err = snd_timer_global_register(timer);
- if (err < 0) {
- snd_timer_global_free(timer);
- return err;
- }
- mytimer = timer; /* remember this */
-
- return 0;
-}
-
-static void __exit snd_hrtimer_exit(void)
-{
- if (mytimer) {
- snd_timer_global_free(mytimer);
- mytimer = NULL;
- }
-}
-
-module_init(snd_hrtimer_init);
-module_exit(snd_hrtimer_exit);
diff --git a/ANDROID_3.4.5/sound/core/hwdep.c b/ANDROID_3.4.5/sound/core/hwdep.c
deleted file mode 100644
index 3f7f6628..00000000
--- a/ANDROID_3.4.5/sound/core/hwdep.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * Hardware dependent layer
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/major.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/minors.h>
-#include <sound/hwdep.h>
-#include <sound/info.h>
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Hardware dependent layer");
-MODULE_LICENSE("GPL");
-
-static LIST_HEAD(snd_hwdep_devices);
-static DEFINE_MUTEX(register_mutex);
-
-static int snd_hwdep_free(struct snd_hwdep *hwdep);
-static int snd_hwdep_dev_free(struct snd_device *device);
-static int snd_hwdep_dev_register(struct snd_device *device);
-static int snd_hwdep_dev_disconnect(struct snd_device *device);
-
-
-static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device)
-{
- struct snd_hwdep *hwdep;
-
- list_for_each_entry(hwdep, &snd_hwdep_devices, list)
- if (hwdep->card == card && hwdep->device == device)
- return hwdep;
- return NULL;
-}
-
-static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
-{
- struct snd_hwdep *hw = file->private_data;
- if (hw->ops.llseek)
- return hw->ops.llseek(hw, file, offset, orig);
- return -ENXIO;
-}
-
-static ssize_t snd_hwdep_read(struct file * file, char __user *buf,
- size_t count, loff_t *offset)
-{
- struct snd_hwdep *hw = file->private_data;
- if (hw->ops.read)
- return hw->ops.read(hw, buf, count, offset);
- return -ENXIO;
-}
-
-static ssize_t snd_hwdep_write(struct file * file, const char __user *buf,
- size_t count, loff_t *offset)
-{
- struct snd_hwdep *hw = file->private_data;
- if (hw->ops.write)
- return hw->ops.write(hw, buf, count, offset);
- return -ENXIO;
-}
-
-static int snd_hwdep_open(struct inode *inode, struct file * file)
-{
- int major = imajor(inode);
- struct snd_hwdep *hw;
- int err;
- wait_queue_t wait;
-
- if (major == snd_major) {
- hw = snd_lookup_minor_data(iminor(inode),
- SNDRV_DEVICE_TYPE_HWDEP);
-#ifdef CONFIG_SND_OSSEMUL
- } else if (major == SOUND_MAJOR) {
- hw = snd_lookup_oss_minor_data(iminor(inode),
- SNDRV_OSS_DEVICE_TYPE_DMFM);
-#endif
- } else
- return -ENXIO;
- if (hw == NULL)
- return -ENODEV;
-
- if (!try_module_get(hw->card->module)) {
- snd_card_unref(hw->card);
- return -EFAULT;
- }
-
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&hw->open_wait, &wait);
- mutex_lock(&hw->open_mutex);
- while (1) {
- if (hw->exclusive && hw->used > 0) {
- err = -EBUSY;
- break;
- }
- if (!hw->ops.open) {
- err = 0;
- break;
- }
- err = hw->ops.open(hw, file);
- if (err >= 0)
- break;
- if (err == -EAGAIN) {
- if (file->f_flags & O_NONBLOCK) {
- err = -EBUSY;
- break;
- }
- } else
- break;
- set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&hw->open_mutex);
- schedule();
- mutex_lock(&hw->open_mutex);
- if (hw->card->shutdown) {
- err = -ENODEV;
- break;
- }
- if (signal_pending(current)) {
- err = -ERESTARTSYS;
- break;
- }
- }
- remove_wait_queue(&hw->open_wait, &wait);
- if (err >= 0) {
- err = snd_card_file_add(hw->card, file);
- if (err >= 0) {
- file->private_data = hw;
- hw->used++;
- } else {
- if (hw->ops.release)
- hw->ops.release(hw, file);
- }
- }
- mutex_unlock(&hw->open_mutex);
- if (err < 0)
- module_put(hw->card->module);
- snd_card_unref(hw->card);
- return err;
-}
-
-static int snd_hwdep_release(struct inode *inode, struct file * file)
-{
- int err = 0;
- struct snd_hwdep *hw = file->private_data;
- struct module *mod = hw->card->module;
-
- mutex_lock(&hw->open_mutex);
- if (hw->ops.release)
- err = hw->ops.release(hw, file);
- if (hw->used > 0)
- hw->used--;
- mutex_unlock(&hw->open_mutex);
- wake_up(&hw->open_wait);
-
- snd_card_file_remove(hw->card, file);
- module_put(mod);
- return err;
-}
-
-static unsigned int snd_hwdep_poll(struct file * file, poll_table * wait)
-{
- struct snd_hwdep *hw = file->private_data;
- if (hw->ops.poll)
- return hw->ops.poll(hw, file, wait);
- return 0;
-}
-
-static int snd_hwdep_info(struct snd_hwdep *hw,
- struct snd_hwdep_info __user *_info)
-{
- struct snd_hwdep_info info;
-
- memset(&info, 0, sizeof(info));
- info.card = hw->card->number;
- strlcpy(info.id, hw->id, sizeof(info.id));
- strlcpy(info.name, hw->name, sizeof(info.name));
- info.iface = hw->iface;
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_hwdep_dsp_status(struct snd_hwdep *hw,
- struct snd_hwdep_dsp_status __user *_info)
-{
- struct snd_hwdep_dsp_status info;
- int err;
-
- if (! hw->ops.dsp_status)
- return -ENXIO;
- memset(&info, 0, sizeof(info));
- info.dsp_loaded = hw->dsp_loaded;
- if ((err = hw->ops.dsp_status(hw, &info)) < 0)
- return err;
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_hwdep_dsp_load(struct snd_hwdep *hw,
- struct snd_hwdep_dsp_image __user *_info)
-{
- struct snd_hwdep_dsp_image info;
- int err;
-
- if (! hw->ops.dsp_load)
- return -ENXIO;
- memset(&info, 0, sizeof(info));
- if (copy_from_user(&info, _info, sizeof(info)))
- return -EFAULT;
- /* check whether the dsp was already loaded */
- if (hw->dsp_loaded & (1 << info.index))
- return -EBUSY;
- if (!access_ok(VERIFY_READ, info.image, info.length))
- return -EFAULT;
- err = hw->ops.dsp_load(hw, &info);
- if (err < 0)
- return err;
- hw->dsp_loaded |= (1 << info.index);
- return 0;
-}
-
-static long snd_hwdep_ioctl(struct file * file, unsigned int cmd,
- unsigned long arg)
-{
- struct snd_hwdep *hw = file->private_data;
- void __user *argp = (void __user *)arg;
- switch (cmd) {
- case SNDRV_HWDEP_IOCTL_PVERSION:
- return put_user(SNDRV_HWDEP_VERSION, (int __user *)argp);
- case SNDRV_HWDEP_IOCTL_INFO:
- return snd_hwdep_info(hw, argp);
- case SNDRV_HWDEP_IOCTL_DSP_STATUS:
- return snd_hwdep_dsp_status(hw, argp);
- case SNDRV_HWDEP_IOCTL_DSP_LOAD:
- return snd_hwdep_dsp_load(hw, argp);
- }
- if (hw->ops.ioctl)
- return hw->ops.ioctl(hw, file, cmd, arg);
- return -ENOTTY;
-}
-
-static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma)
-{
- struct snd_hwdep *hw = file->private_data;
- if (hw->ops.mmap)
- return hw->ops.mmap(hw, file, vma);
- return -ENXIO;
-}
-
-static int snd_hwdep_control_ioctl(struct snd_card *card,
- struct snd_ctl_file * control,
- unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
- {
- int device;
-
- if (get_user(device, (int __user *)arg))
- return -EFAULT;
- mutex_lock(&register_mutex);
-
- if (device < 0)
- device = 0;
- else if (device < SNDRV_MINOR_HWDEPS)
- device++;
- else
- device = SNDRV_MINOR_HWDEPS;
-
- while (device < SNDRV_MINOR_HWDEPS) {
- if (snd_hwdep_search(card, device))
- break;
- device++;
- }
- if (device >= SNDRV_MINOR_HWDEPS)
- device = -1;
- mutex_unlock(&register_mutex);
- if (put_user(device, (int __user *)arg))
- return -EFAULT;
- return 0;
- }
- case SNDRV_CTL_IOCTL_HWDEP_INFO:
- {
- struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg;
- int device, err;
- struct snd_hwdep *hwdep;
-
- if (get_user(device, &info->device))
- return -EFAULT;
- mutex_lock(&register_mutex);
- hwdep = snd_hwdep_search(card, device);
- if (hwdep)
- err = snd_hwdep_info(hwdep, info);
- else
- err = -ENXIO;
- mutex_unlock(&register_mutex);
- return err;
- }
- }
- return -ENOIOCTLCMD;
-}
-
-#ifdef CONFIG_COMPAT
-#include "hwdep_compat.c"
-#else
-#define snd_hwdep_ioctl_compat NULL
-#endif
-
-/*
-
- */
-
-static const struct file_operations snd_hwdep_f_ops =
-{
- .owner = THIS_MODULE,
- .llseek = snd_hwdep_llseek,
- .read = snd_hwdep_read,
- .write = snd_hwdep_write,
- .open = snd_hwdep_open,
- .release = snd_hwdep_release,
- .poll = snd_hwdep_poll,
- .unlocked_ioctl = snd_hwdep_ioctl,
- .compat_ioctl = snd_hwdep_ioctl_compat,
- .mmap = snd_hwdep_mmap,
-};
-
-/**
- * snd_hwdep_new - create a new hwdep instance
- * @card: the card instance
- * @id: the id string
- * @device: the device index (zero-based)
- * @rhwdep: the pointer to store the new hwdep instance
- *
- * Creates a new hwdep instance with the given index on the card.
- * The callbacks (hwdep->ops) must be set on the returned instance
- * after this call manually by the caller.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_hwdep_new(struct snd_card *card, char *id, int device,
- struct snd_hwdep **rhwdep)
-{
- struct snd_hwdep *hwdep;
- int err;
- static struct snd_device_ops ops = {
- .dev_free = snd_hwdep_dev_free,
- .dev_register = snd_hwdep_dev_register,
- .dev_disconnect = snd_hwdep_dev_disconnect,
- };
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- if (rhwdep)
- *rhwdep = NULL;
- hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL);
- if (hwdep == NULL) {
- snd_printk(KERN_ERR "hwdep: cannot allocate\n");
- return -ENOMEM;
- }
- hwdep->card = card;
- hwdep->device = device;
- if (id)
- strlcpy(hwdep->id, id, sizeof(hwdep->id));
-#ifdef CONFIG_SND_OSSEMUL
- hwdep->oss_type = -1;
-#endif
- if ((err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops)) < 0) {
- snd_hwdep_free(hwdep);
- return err;
- }
- init_waitqueue_head(&hwdep->open_wait);
- mutex_init(&hwdep->open_mutex);
- if (rhwdep)
- *rhwdep = hwdep;
- return 0;
-}
-
-static int snd_hwdep_free(struct snd_hwdep *hwdep)
-{
- if (!hwdep)
- return 0;
- if (hwdep->private_free)
- hwdep->private_free(hwdep);
- kfree(hwdep);
- return 0;
-}
-
-static int snd_hwdep_dev_free(struct snd_device *device)
-{
- struct snd_hwdep *hwdep = device->device_data;
- return snd_hwdep_free(hwdep);
-}
-
-static int snd_hwdep_dev_register(struct snd_device *device)
-{
- struct snd_hwdep *hwdep = device->device_data;
- int err;
- char name[32];
-
- mutex_lock(&register_mutex);
- if (snd_hwdep_search(hwdep->card, hwdep->device)) {
- mutex_unlock(&register_mutex);
- return -EBUSY;
- }
- list_add_tail(&hwdep->list, &snd_hwdep_devices);
- sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device);
- if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
- hwdep->card, hwdep->device,
- &snd_hwdep_f_ops, hwdep, name)) < 0) {
- snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n",
- hwdep->card->number, hwdep->device);
- list_del(&hwdep->list);
- mutex_unlock(&register_mutex);
- return err;
- }
-#ifdef CONFIG_SND_OSSEMUL
- hwdep->ossreg = 0;
- if (hwdep->oss_type >= 0) {
- if ((hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM) && (hwdep->device != 0)) {
- snd_printk (KERN_WARNING "only hwdep device 0 can be registered as OSS direct FM device!\n");
- } else {
- if (snd_register_oss_device(hwdep->oss_type,
- hwdep->card, hwdep->device,
- &snd_hwdep_f_ops, hwdep,
- hwdep->oss_dev) < 0) {
- snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n",
- hwdep->card->number, hwdep->device);
- } else
- hwdep->ossreg = 1;
- }
- }
-#endif
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-static int snd_hwdep_dev_disconnect(struct snd_device *device)
-{
- struct snd_hwdep *hwdep = device->device_data;
-
- if (snd_BUG_ON(!hwdep))
- return -ENXIO;
- mutex_lock(&register_mutex);
- if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) {
- mutex_unlock(&register_mutex);
- return -EINVAL;
- }
- mutex_lock(&hwdep->open_mutex);
- wake_up(&hwdep->open_wait);
-#ifdef CONFIG_SND_OSSEMUL
- if (hwdep->ossreg)
- snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
-#endif
- snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
- list_del_init(&hwdep->list);
- mutex_unlock(&hwdep->open_mutex);
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-#ifdef CONFIG_PROC_FS
-/*
- * Info interface
- */
-
-static void snd_hwdep_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_hwdep *hwdep;
-
- mutex_lock(&register_mutex);
- list_for_each_entry(hwdep, &snd_hwdep_devices, list)
- snd_iprintf(buffer, "%02i-%02i: %s\n",
- hwdep->card->number, hwdep->device, hwdep->name);
- mutex_unlock(&register_mutex);
-}
-
-static struct snd_info_entry *snd_hwdep_proc_entry;
-
-static void __init snd_hwdep_proc_init(void)
-{
- struct snd_info_entry *entry;
-
- if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) {
- entry->c.text.read = snd_hwdep_proc_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- snd_hwdep_proc_entry = entry;
-}
-
-static void __exit snd_hwdep_proc_done(void)
-{
- snd_info_free_entry(snd_hwdep_proc_entry);
-}
-#else /* !CONFIG_PROC_FS */
-#define snd_hwdep_proc_init()
-#define snd_hwdep_proc_done()
-#endif /* CONFIG_PROC_FS */
-
-
-/*
- * ENTRY functions
- */
-
-static int __init alsa_hwdep_init(void)
-{
- snd_hwdep_proc_init();
- snd_ctl_register_ioctl(snd_hwdep_control_ioctl);
- snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl);
- return 0;
-}
-
-static void __exit alsa_hwdep_exit(void)
-{
- snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl);
- snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl);
- snd_hwdep_proc_done();
-}
-
-module_init(alsa_hwdep_init)
-module_exit(alsa_hwdep_exit)
-
-EXPORT_SYMBOL(snd_hwdep_new);
diff --git a/ANDROID_3.4.5/sound/core/hwdep_compat.c b/ANDROID_3.4.5/sound/core/hwdep_compat.c
deleted file mode 100644
index 3827c0ce..00000000
--- a/ANDROID_3.4.5/sound/core/hwdep_compat.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for hwdep API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/* This file is included from hwdep.c */
-
-#include <linux/compat.h>
-
-struct snd_hwdep_dsp_image32 {
- u32 index;
- unsigned char name[64];
- u32 image; /* pointer */
- u32 length;
- u32 driver_data;
-} /* don't set packed attribute here */;
-
-static int snd_hwdep_dsp_load_compat(struct snd_hwdep *hw,
- struct snd_hwdep_dsp_image32 __user *src)
-{
- struct snd_hwdep_dsp_image __user *dst;
- compat_caddr_t ptr;
- u32 val;
-
- dst = compat_alloc_user_space(sizeof(*dst));
-
- /* index and name */
- if (copy_in_user(dst, src, 4 + 64))
- return -EFAULT;
- if (get_user(ptr, &src->image) ||
- put_user(compat_ptr(ptr), &dst->image))
- return -EFAULT;
- if (get_user(val, &src->length) ||
- put_user(val, &dst->length))
- return -EFAULT;
- if (get_user(val, &src->driver_data) ||
- put_user(val, &dst->driver_data))
- return -EFAULT;
-
- return snd_hwdep_dsp_load(hw, dst);
-}
-
-enum {
- SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct snd_hwdep_dsp_image32)
-};
-
-static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd,
- unsigned long arg)
-{
- struct snd_hwdep *hw = file->private_data;
- void __user *argp = compat_ptr(arg);
- switch (cmd) {
- case SNDRV_HWDEP_IOCTL_PVERSION:
- case SNDRV_HWDEP_IOCTL_INFO:
- case SNDRV_HWDEP_IOCTL_DSP_STATUS:
- return snd_hwdep_ioctl(file, cmd, (unsigned long)argp);
- case SNDRV_HWDEP_IOCTL_DSP_LOAD32:
- return snd_hwdep_dsp_load_compat(hw, argp);
- }
- if (hw->ops.ioctl_compat)
- return hw->ops.ioctl_compat(hw, file, cmd, arg);
- return -ENOIOCTLCMD;
-}
diff --git a/ANDROID_3.4.5/sound/core/info.c b/ANDROID_3.4.5/sound/core/info.c
deleted file mode 100644
index c1e611c6..00000000
--- a/ANDROID_3.4.5/sound/core/info.c
+++ /dev/null
@@ -1,1016 +0,0 @@
-/*
- * Information interface for ALSA driver
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <sound/info.h>
-#include <sound/version.h>
-#include <linux/proc_fs.h>
-#include <linux/mutex.h>
-#include <stdarg.h>
-
-/*
- *
- */
-
-#ifdef CONFIG_PROC_FS
-
-int snd_info_check_reserved_words(const char *str)
-{
- static char *reserved[] =
- {
- "version",
- "meminfo",
- "memdebug",
- "detect",
- "devices",
- "oss",
- "cards",
- "timers",
- "synth",
- "pcm",
- "seq",
- NULL
- };
- char **xstr = reserved;
-
- while (*xstr) {
- if (!strcmp(*xstr, str))
- return 0;
- xstr++;
- }
- if (!strncmp(str, "card", 4))
- return 0;
- return 1;
-}
-
-static DEFINE_MUTEX(info_mutex);
-
-struct snd_info_private_data {
- struct snd_info_buffer *rbuffer;
- struct snd_info_buffer *wbuffer;
- struct snd_info_entry *entry;
- void *file_private_data;
-};
-
-static int snd_info_version_init(void);
-static int snd_info_version_done(void);
-static void snd_info_disconnect(struct snd_info_entry *entry);
-
-
-/* resize the proc r/w buffer */
-static int resize_info_buffer(struct snd_info_buffer *buffer,
- unsigned int nsize)
-{
- char *nbuf;
-
- nsize = PAGE_ALIGN(nsize);
- nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL);
- if (! nbuf)
- return -ENOMEM;
-
- buffer->buffer = nbuf;
- buffer->len = nsize;
- return 0;
-}
-
-/**
- * snd_iprintf - printf on the procfs buffer
- * @buffer: the procfs buffer
- * @fmt: the printf format
- *
- * Outputs the string on the procfs buffer just like printf().
- *
- * Returns the size of output string.
- */
-int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...)
-{
- va_list args;
- int len, res;
- int err = 0;
-
- might_sleep();
- if (buffer->stop || buffer->error)
- return 0;
- len = buffer->len - buffer->size;
- va_start(args, fmt);
- for (;;) {
- va_list ap;
- va_copy(ap, args);
- res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, ap);
- va_end(ap);
- if (res < len)
- break;
- err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE);
- if (err < 0)
- break;
- len = buffer->len - buffer->size;
- }
- va_end(args);
-
- if (err < 0)
- return err;
- buffer->curr += res;
- buffer->size += res;
- return res;
-}
-
-EXPORT_SYMBOL(snd_iprintf);
-
-/*
-
- */
-
-static struct proc_dir_entry *snd_proc_root;
-struct snd_info_entry *snd_seq_root;
-EXPORT_SYMBOL(snd_seq_root);
-
-#ifdef CONFIG_SND_OSSEMUL
-struct snd_info_entry *snd_oss_root;
-#endif
-
-static void snd_remove_proc_entry(struct proc_dir_entry *parent,
- struct proc_dir_entry *de)
-{
- if (de)
- remove_proc_entry(de->name, parent);
-}
-
-static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
-{
- struct snd_info_private_data *data;
- struct snd_info_entry *entry;
- loff_t ret = -EINVAL, size;
-
- data = file->private_data;
- entry = data->entry;
- mutex_lock(&entry->access);
- if (entry->content == SNDRV_INFO_CONTENT_DATA &&
- entry->c.ops->llseek) {
- offset = entry->c.ops->llseek(entry,
- data->file_private_data,
- file, offset, orig);
- goto out;
- }
- if (entry->content == SNDRV_INFO_CONTENT_DATA)
- size = entry->size;
- else
- size = 0;
- switch (orig) {
- case SEEK_SET:
- break;
- case SEEK_CUR:
- offset += file->f_pos;
- break;
- case SEEK_END:
- if (!size)
- goto out;
- offset += size;
- break;
- default:
- goto out;
- }
- if (offset < 0)
- goto out;
- if (size && offset > size)
- offset = size;
- file->f_pos = offset;
- ret = offset;
- out:
- mutex_unlock(&entry->access);
- return ret;
-}
-
-static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
- size_t count, loff_t * offset)
-{
- struct snd_info_private_data *data;
- struct snd_info_entry *entry;
- struct snd_info_buffer *buf;
- size_t size = 0;
- loff_t pos;
-
- data = file->private_data;
- if (snd_BUG_ON(!data))
- return -ENXIO;
- pos = *offset;
- if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
- return -EIO;
- if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos)
- return -EIO;
- entry = data->entry;
- switch (entry->content) {
- case SNDRV_INFO_CONTENT_TEXT:
- buf = data->rbuffer;
- if (buf == NULL)
- return -EIO;
- if (pos >= buf->size)
- return 0;
- size = buf->size - pos;
- size = min(count, size);
- if (copy_to_user(buffer, buf->buffer + pos, size))
- return -EFAULT;
- break;
- case SNDRV_INFO_CONTENT_DATA:
- if (pos >= entry->size)
- return 0;
- if (entry->c.ops->read) {
- size = entry->size - pos;
- size = min(count, size);
- size = entry->c.ops->read(entry,
- data->file_private_data,
- file, buffer, size, pos);
- }
- break;
- }
- if ((ssize_t) size > 0)
- *offset = pos + size;
- return size;
-}
-
-static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer,
- size_t count, loff_t * offset)
-{
- struct snd_info_private_data *data;
- struct snd_info_entry *entry;
- struct snd_info_buffer *buf;
- ssize_t size = 0;
- loff_t pos;
-
- data = file->private_data;
- if (snd_BUG_ON(!data))
- return -ENXIO;
- entry = data->entry;
- pos = *offset;
- if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
- return -EIO;
- if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos)
- return -EIO;
- switch (entry->content) {
- case SNDRV_INFO_CONTENT_TEXT:
- buf = data->wbuffer;
- if (buf == NULL)
- return -EIO;
- mutex_lock(&entry->access);
- if (pos + count >= buf->len) {
- if (resize_info_buffer(buf, pos + count)) {
- mutex_unlock(&entry->access);
- return -ENOMEM;
- }
- }
- if (copy_from_user(buf->buffer + pos, buffer, count)) {
- mutex_unlock(&entry->access);
- return -EFAULT;
- }
- buf->size = pos + count;
- mutex_unlock(&entry->access);
- size = count;
- break;
- case SNDRV_INFO_CONTENT_DATA:
- if (entry->c.ops->write && count > 0) {
- size_t maxsize = entry->size - pos;
- count = min(count, maxsize);
- size = entry->c.ops->write(entry,
- data->file_private_data,
- file, buffer, count, pos);
- }
- break;
- }
- if ((ssize_t) size > 0)
- *offset = pos + size;
- return size;
-}
-
-static int snd_info_entry_open(struct inode *inode, struct file *file)
-{
- struct snd_info_entry *entry;
- struct snd_info_private_data *data;
- struct snd_info_buffer *buffer;
- struct proc_dir_entry *p;
- int mode, err;
-
- mutex_lock(&info_mutex);
- p = PDE(inode);
- entry = p == NULL ? NULL : (struct snd_info_entry *)p->data;
- if (entry == NULL || ! entry->p) {
- mutex_unlock(&info_mutex);
- return -ENODEV;
- }
- if (!try_module_get(entry->module)) {
- err = -EFAULT;
- goto __error1;
- }
- mode = file->f_flags & O_ACCMODE;
- if (mode == O_RDONLY || mode == O_RDWR) {
- if ((entry->content == SNDRV_INFO_CONTENT_DATA &&
- entry->c.ops->read == NULL)) {
- err = -ENODEV;
- goto __error;
- }
- }
- if (mode == O_WRONLY || mode == O_RDWR) {
- if ((entry->content == SNDRV_INFO_CONTENT_DATA &&
- entry->c.ops->write == NULL)) {
- err = -ENODEV;
- goto __error;
- }
- }
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (data == NULL) {
- err = -ENOMEM;
- goto __error;
- }
- data->entry = entry;
- switch (entry->content) {
- case SNDRV_INFO_CONTENT_TEXT:
- if (mode == O_RDONLY || mode == O_RDWR) {
- buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
- if (buffer == NULL)
- goto __nomem;
- data->rbuffer = buffer;
- buffer->len = PAGE_SIZE;
- buffer->buffer = kmalloc(buffer->len, GFP_KERNEL);
- if (buffer->buffer == NULL)
- goto __nomem;
- }
- if (mode == O_WRONLY || mode == O_RDWR) {
- buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
- if (buffer == NULL)
- goto __nomem;
- data->wbuffer = buffer;
- buffer->len = PAGE_SIZE;
- buffer->buffer = kmalloc(buffer->len, GFP_KERNEL);
- if (buffer->buffer == NULL)
- goto __nomem;
- }
- break;
- case SNDRV_INFO_CONTENT_DATA: /* data */
- if (entry->c.ops->open) {
- if ((err = entry->c.ops->open(entry, mode,
- &data->file_private_data)) < 0) {
- kfree(data);
- goto __error;
- }
- }
- break;
- }
- file->private_data = data;
- mutex_unlock(&info_mutex);
- if (entry->content == SNDRV_INFO_CONTENT_TEXT &&
- (mode == O_RDONLY || mode == O_RDWR)) {
- if (entry->c.text.read) {
- mutex_lock(&entry->access);
- entry->c.text.read(entry, data->rbuffer);
- mutex_unlock(&entry->access);
- }
- }
- return 0;
-
- __nomem:
- if (data->rbuffer) {
- kfree(data->rbuffer->buffer);
- kfree(data->rbuffer);
- }
- if (data->wbuffer) {
- kfree(data->wbuffer->buffer);
- kfree(data->wbuffer);
- }
- kfree(data);
- err = -ENOMEM;
- __error:
- module_put(entry->module);
- __error1:
- mutex_unlock(&info_mutex);
- return err;
-}
-
-static int snd_info_entry_release(struct inode *inode, struct file *file)
-{
- struct snd_info_entry *entry;
- struct snd_info_private_data *data;
- int mode;
-
- mode = file->f_flags & O_ACCMODE;
- data = file->private_data;
- entry = data->entry;
- switch (entry->content) {
- case SNDRV_INFO_CONTENT_TEXT:
- if (data->rbuffer) {
- kfree(data->rbuffer->buffer);
- kfree(data->rbuffer);
- }
- if (data->wbuffer) {
- if (entry->c.text.write) {
- entry->c.text.write(entry, data->wbuffer);
- if (data->wbuffer->error) {
- snd_printk(KERN_WARNING "data write error to %s (%i)\n",
- entry->name,
- data->wbuffer->error);
- }
- }
- kfree(data->wbuffer->buffer);
- kfree(data->wbuffer);
- }
- break;
- case SNDRV_INFO_CONTENT_DATA:
- if (entry->c.ops->release)
- entry->c.ops->release(entry, mode,
- data->file_private_data);
- break;
- }
- module_put(entry->module);
- kfree(data);
- return 0;
-}
-
-static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait)
-{
- struct snd_info_private_data *data;
- struct snd_info_entry *entry;
- unsigned int mask;
-
- data = file->private_data;
- if (data == NULL)
- return 0;
- entry = data->entry;
- mask = 0;
- switch (entry->content) {
- case SNDRV_INFO_CONTENT_DATA:
- if (entry->c.ops->poll)
- return entry->c.ops->poll(entry,
- data->file_private_data,
- file, wait);
- if (entry->c.ops->read)
- mask |= POLLIN | POLLRDNORM;
- if (entry->c.ops->write)
- mask |= POLLOUT | POLLWRNORM;
- break;
- }
- return mask;
-}
-
-static long snd_info_entry_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct snd_info_private_data *data;
- struct snd_info_entry *entry;
-
- data = file->private_data;
- if (data == NULL)
- return 0;
- entry = data->entry;
- switch (entry->content) {
- case SNDRV_INFO_CONTENT_DATA:
- if (entry->c.ops->ioctl)
- return entry->c.ops->ioctl(entry,
- data->file_private_data,
- file, cmd, arg);
- break;
- }
- return -ENOTTY;
-}
-
-static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct inode *inode = file->f_path.dentry->d_inode;
- struct snd_info_private_data *data;
- struct snd_info_entry *entry;
-
- data = file->private_data;
- if (data == NULL)
- return 0;
- entry = data->entry;
- switch (entry->content) {
- case SNDRV_INFO_CONTENT_DATA:
- if (entry->c.ops->mmap)
- return entry->c.ops->mmap(entry,
- data->file_private_data,
- inode, file, vma);
- break;
- }
- return -ENXIO;
-}
-
-static const struct file_operations snd_info_entry_operations =
-{
- .owner = THIS_MODULE,
- .llseek = snd_info_entry_llseek,
- .read = snd_info_entry_read,
- .write = snd_info_entry_write,
- .poll = snd_info_entry_poll,
- .unlocked_ioctl = snd_info_entry_ioctl,
- .mmap = snd_info_entry_mmap,
- .open = snd_info_entry_open,
- .release = snd_info_entry_release,
-};
-
-int __init snd_info_init(void)
-{
- struct proc_dir_entry *p;
-
- p = proc_mkdir("asound", NULL);
- if (p == NULL)
- return -ENOMEM;
- snd_proc_root = p;
-#ifdef CONFIG_SND_OSSEMUL
- {
- struct snd_info_entry *entry;
- if ((entry = snd_info_create_module_entry(THIS_MODULE, "oss", NULL)) == NULL)
- return -ENOMEM;
- entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
- snd_oss_root = entry;
- }
-#endif
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
- {
- struct snd_info_entry *entry;
- if ((entry = snd_info_create_module_entry(THIS_MODULE, "seq", NULL)) == NULL)
- return -ENOMEM;
- entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
- snd_seq_root = entry;
- }
-#endif
- snd_info_version_init();
- snd_minor_info_init();
- snd_minor_info_oss_init();
- snd_card_info_init();
- return 0;
-}
-
-int __exit snd_info_done(void)
-{
- snd_card_info_done();
- snd_minor_info_oss_done();
- snd_minor_info_done();
- snd_info_version_done();
- if (snd_proc_root) {
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
- snd_info_free_entry(snd_seq_root);
-#endif
-#ifdef CONFIG_SND_OSSEMUL
- snd_info_free_entry(snd_oss_root);
-#endif
- snd_remove_proc_entry(NULL, snd_proc_root);
- }
- return 0;
-}
-
-/*
-
- */
-
-
-/*
- * create a card proc file
- * called from init.c
- */
-int snd_info_card_create(struct snd_card *card)
-{
- char str[8];
- struct snd_info_entry *entry;
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
-
- sprintf(str, "card%i", card->number);
- if ((entry = snd_info_create_module_entry(card->module, str, NULL)) == NULL)
- return -ENOMEM;
- entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
- card->proc_root = entry;
- return 0;
-}
-
-/*
- * register the card proc file
- * called from init.c
- */
-int snd_info_card_register(struct snd_card *card)
-{
- struct proc_dir_entry *p;
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
-
- if (!strcmp(card->id, card->proc_root->name))
- return 0;
-
- p = proc_symlink(card->id, snd_proc_root, card->proc_root->name);
- if (p == NULL)
- return -ENOMEM;
- card->proc_root_link = p;
- return 0;
-}
-
-/*
- * called on card->id change
- */
-void snd_info_card_id_change(struct snd_card *card)
-{
- mutex_lock(&info_mutex);
- if (card->proc_root_link) {
- snd_remove_proc_entry(snd_proc_root, card->proc_root_link);
- card->proc_root_link = NULL;
- }
- if (strcmp(card->id, card->proc_root->name))
- card->proc_root_link = proc_symlink(card->id,
- snd_proc_root,
- card->proc_root->name);
- mutex_unlock(&info_mutex);
-}
-
-/*
- * de-register the card proc file
- * called from init.c
- */
-void snd_info_card_disconnect(struct snd_card *card)
-{
- if (!card)
- return;
- mutex_lock(&info_mutex);
- if (card->proc_root_link) {
- snd_remove_proc_entry(snd_proc_root, card->proc_root_link);
- card->proc_root_link = NULL;
- }
- if (card->proc_root)
- snd_info_disconnect(card->proc_root);
- mutex_unlock(&info_mutex);
-}
-
-/*
- * release the card proc file resources
- * called from init.c
- */
-int snd_info_card_free(struct snd_card *card)
-{
- if (!card)
- return 0;
- snd_info_free_entry(card->proc_root);
- card->proc_root = NULL;
- return 0;
-}
-
-
-/**
- * snd_info_get_line - read one line from the procfs buffer
- * @buffer: the procfs buffer
- * @line: the buffer to store
- * @len: the max. buffer size - 1
- *
- * Reads one line from the buffer and stores the string.
- *
- * Returns zero if successful, or 1 if error or EOF.
- */
-int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
-{
- int c = -1;
-
- if (len <= 0 || buffer->stop || buffer->error)
- return 1;
- while (--len > 0) {
- c = buffer->buffer[buffer->curr++];
- if (c == '\n') {
- if (buffer->curr >= buffer->size)
- buffer->stop = 1;
- break;
- }
- *line++ = c;
- if (buffer->curr >= buffer->size) {
- buffer->stop = 1;
- break;
- }
- }
- while (c != '\n' && !buffer->stop) {
- c = buffer->buffer[buffer->curr++];
- if (buffer->curr >= buffer->size)
- buffer->stop = 1;
- }
- *line = '\0';
- return 0;
-}
-
-EXPORT_SYMBOL(snd_info_get_line);
-
-/**
- * snd_info_get_str - parse a string token
- * @dest: the buffer to store the string token
- * @src: the original string
- * @len: the max. length of token - 1
- *
- * Parses the original string and copy a token to the given
- * string buffer.
- *
- * Returns the updated pointer of the original string so that
- * it can be used for the next call.
- */
-const char *snd_info_get_str(char *dest, const char *src, int len)
-{
- int c;
-
- while (*src == ' ' || *src == '\t')
- src++;
- if (*src == '"' || *src == '\'') {
- c = *src++;
- while (--len > 0 && *src && *src != c) {
- *dest++ = *src++;
- }
- if (*src == c)
- src++;
- } else {
- while (--len > 0 && *src && *src != ' ' && *src != '\t') {
- *dest++ = *src++;
- }
- }
- *dest = 0;
- while (*src == ' ' || *src == '\t')
- src++;
- return src;
-}
-
-EXPORT_SYMBOL(snd_info_get_str);
-
-/**
- * snd_info_create_entry - create an info entry
- * @name: the proc file name
- *
- * Creates an info entry with the given file name and initializes as
- * the default state.
- *
- * Usually called from other functions such as
- * snd_info_create_card_entry().
- *
- * Returns the pointer of the new instance, or NULL on failure.
- */
-static struct snd_info_entry *snd_info_create_entry(const char *name)
-{
- struct snd_info_entry *entry;
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (entry == NULL)
- return NULL;
- entry->name = kstrdup(name, GFP_KERNEL);
- if (entry->name == NULL) {
- kfree(entry);
- return NULL;
- }
- entry->mode = S_IFREG | S_IRUGO;
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- mutex_init(&entry->access);
- INIT_LIST_HEAD(&entry->children);
- INIT_LIST_HEAD(&entry->list);
- return entry;
-}
-
-/**
- * snd_info_create_module_entry - create an info entry for the given module
- * @module: the module pointer
- * @name: the file name
- * @parent: the parent directory
- *
- * Creates a new info entry and assigns it to the given module.
- *
- * Returns the pointer of the new instance, or NULL on failure.
- */
-struct snd_info_entry *snd_info_create_module_entry(struct module * module,
- const char *name,
- struct snd_info_entry *parent)
-{
- struct snd_info_entry *entry = snd_info_create_entry(name);
- if (entry) {
- entry->module = module;
- entry->parent = parent;
- }
- return entry;
-}
-
-EXPORT_SYMBOL(snd_info_create_module_entry);
-
-/**
- * snd_info_create_card_entry - create an info entry for the given card
- * @card: the card instance
- * @name: the file name
- * @parent: the parent directory
- *
- * Creates a new info entry and assigns it to the given card.
- *
- * Returns the pointer of the new instance, or NULL on failure.
- */
-struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
- const char *name,
- struct snd_info_entry * parent)
-{
- struct snd_info_entry *entry = snd_info_create_entry(name);
- if (entry) {
- entry->module = card->module;
- entry->card = card;
- entry->parent = parent;
- }
- return entry;
-}
-
-EXPORT_SYMBOL(snd_info_create_card_entry);
-
-static void snd_info_disconnect(struct snd_info_entry *entry)
-{
- struct list_head *p, *n;
- struct proc_dir_entry *root;
-
- list_for_each_safe(p, n, &entry->children) {
- snd_info_disconnect(list_entry(p, struct snd_info_entry, list));
- }
-
- if (! entry->p)
- return;
- list_del_init(&entry->list);
- root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
- snd_BUG_ON(!root);
- snd_remove_proc_entry(root, entry->p);
- entry->p = NULL;
-}
-
-static int snd_info_dev_free_entry(struct snd_device *device)
-{
- struct snd_info_entry *entry = device->device_data;
- snd_info_free_entry(entry);
- return 0;
-}
-
-static int snd_info_dev_register_entry(struct snd_device *device)
-{
- struct snd_info_entry *entry = device->device_data;
- return snd_info_register(entry);
-}
-
-/**
- * snd_card_proc_new - create an info entry for the given card
- * @card: the card instance
- * @name: the file name
- * @entryp: the pointer to store the new info entry
- *
- * Creates a new info entry and assigns it to the given card.
- * Unlike snd_info_create_card_entry(), this function registers the
- * info entry as an ALSA device component, so that it can be
- * unregistered/released without explicit call.
- * Also, you don't have to register this entry via snd_info_register(),
- * since this will be registered by snd_card_register() automatically.
- *
- * The parent is assumed as card->proc_root.
- *
- * For releasing this entry, use snd_device_free() instead of
- * snd_info_free_entry().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_card_proc_new(struct snd_card *card, const char *name,
- struct snd_info_entry **entryp)
-{
- static struct snd_device_ops ops = {
- .dev_free = snd_info_dev_free_entry,
- .dev_register = snd_info_dev_register_entry,
- /* disconnect is done via snd_info_card_disconnect() */
- };
- struct snd_info_entry *entry;
- int err;
-
- entry = snd_info_create_card_entry(card, name, card->proc_root);
- if (! entry)
- return -ENOMEM;
- if ((err = snd_device_new(card, SNDRV_DEV_INFO, entry, &ops)) < 0) {
- snd_info_free_entry(entry);
- return err;
- }
- if (entryp)
- *entryp = entry;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_card_proc_new);
-
-/**
- * snd_info_free_entry - release the info entry
- * @entry: the info entry
- *
- * Releases the info entry. Don't call this after registered.
- */
-void snd_info_free_entry(struct snd_info_entry * entry)
-{
- if (entry == NULL)
- return;
- if (entry->p) {
- mutex_lock(&info_mutex);
- snd_info_disconnect(entry);
- mutex_unlock(&info_mutex);
- }
- kfree(entry->name);
- if (entry->private_free)
- entry->private_free(entry);
- kfree(entry);
-}
-
-EXPORT_SYMBOL(snd_info_free_entry);
-
-/**
- * snd_info_register - register the info entry
- * @entry: the info entry
- *
- * Registers the proc info entry.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_info_register(struct snd_info_entry * entry)
-{
- struct proc_dir_entry *root, *p = NULL;
-
- if (snd_BUG_ON(!entry))
- return -ENXIO;
- root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
- mutex_lock(&info_mutex);
- p = create_proc_entry(entry->name, entry->mode, root);
- if (!p) {
- mutex_unlock(&info_mutex);
- return -ENOMEM;
- }
- if (!S_ISDIR(entry->mode))
- p->proc_fops = &snd_info_entry_operations;
- p->size = entry->size;
- p->data = entry;
- entry->p = p;
- if (entry->parent)
- list_add_tail(&entry->list, &entry->parent->children);
- mutex_unlock(&info_mutex);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_info_register);
-
-/*
-
- */
-
-static struct snd_info_entry *snd_info_version_entry;
-
-static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
-{
- snd_iprintf(buffer,
- "Advanced Linux Sound Architecture Driver Version "
- CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"
- );
-}
-
-static int __init snd_info_version_init(void)
-{
- struct snd_info_entry *entry;
-
- entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL);
- if (entry == NULL)
- return -ENOMEM;
- entry->c.text.read = snd_info_version_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
- snd_info_version_entry = entry;
- return 0;
-}
-
-static int __exit snd_info_version_done(void)
-{
- snd_info_free_entry(snd_info_version_entry);
- return 0;
-}
-
-#endif /* CONFIG_PROC_FS */
diff --git a/ANDROID_3.4.5/sound/core/info_oss.c b/ANDROID_3.4.5/sound/core/info_oss.c
deleted file mode 100644
index cf42ab50..00000000
--- a/ANDROID_3.4.5/sound/core/info_oss.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Information interface for ALSA driver
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/string.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <sound/info.h>
-#include <sound/version.h>
-#include <linux/utsname.h>
-#include <linux/mutex.h>
-
-#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
-
-/*
- * OSS compatible part
- */
-
-static DEFINE_MUTEX(strings);
-static char *snd_sndstat_strings[SNDRV_CARDS][SNDRV_OSS_INFO_DEV_COUNT];
-static struct snd_info_entry *snd_sndstat_proc_entry;
-
-int snd_oss_info_register(int dev, int num, char *string)
-{
- char *x;
-
- if (snd_BUG_ON(dev < 0 || dev >= SNDRV_OSS_INFO_DEV_COUNT))
- return -ENXIO;
- if (snd_BUG_ON(num < 0 || num >= SNDRV_CARDS))
- return -ENXIO;
- mutex_lock(&strings);
- if (string == NULL) {
- if ((x = snd_sndstat_strings[num][dev]) != NULL) {
- kfree(x);
- x = NULL;
- }
- } else {
- x = kstrdup(string, GFP_KERNEL);
- if (x == NULL) {
- mutex_unlock(&strings);
- return -ENOMEM;
- }
- }
- snd_sndstat_strings[num][dev] = x;
- mutex_unlock(&strings);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_oss_info_register);
-
-static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev)
-{
- int idx, ok = -1;
- char *str;
-
- snd_iprintf(buf, "\n%s:", id);
- mutex_lock(&strings);
- for (idx = 0; idx < SNDRV_CARDS; idx++) {
- str = snd_sndstat_strings[idx][dev];
- if (str) {
- if (ok < 0) {
- snd_iprintf(buf, "\n");
- ok++;
- }
- snd_iprintf(buf, "%i: %s\n", idx, str);
- }
- }
- mutex_unlock(&strings);
- if (ok < 0)
- snd_iprintf(buf, " NOT ENABLED IN CONFIG\n");
- return ok;
-}
-
-static void snd_sndstat_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA v" CONFIG_SND_VERSION " emulation code)\n");
- snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n",
- init_utsname()->sysname,
- init_utsname()->nodename,
- init_utsname()->release,
- init_utsname()->version,
- init_utsname()->machine);
- snd_iprintf(buffer, "Config options: 0\n");
- snd_iprintf(buffer, "\nInstalled drivers: \n");
- snd_iprintf(buffer, "Type 10: ALSA emulation\n");
- snd_iprintf(buffer, "\nCard config: \n");
- snd_card_info_read_oss(buffer);
- snd_sndstat_show_strings(buffer, "Audio devices", SNDRV_OSS_INFO_DEV_AUDIO);
- snd_sndstat_show_strings(buffer, "Synth devices", SNDRV_OSS_INFO_DEV_SYNTH);
- snd_sndstat_show_strings(buffer, "Midi devices", SNDRV_OSS_INFO_DEV_MIDI);
- snd_sndstat_show_strings(buffer, "Timers", SNDRV_OSS_INFO_DEV_TIMERS);
- snd_sndstat_show_strings(buffer, "Mixers", SNDRV_OSS_INFO_DEV_MIXERS);
-}
-
-int snd_info_minor_register(void)
-{
- struct snd_info_entry *entry;
-
- memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings));
- if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) {
- entry->c.text.read = snd_sndstat_proc_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- snd_sndstat_proc_entry = entry;
- return 0;
-}
-
-int snd_info_minor_unregister(void)
-{
- snd_info_free_entry(snd_sndstat_proc_entry);
- snd_sndstat_proc_entry = NULL;
- return 0;
-}
-
-#endif /* CONFIG_SND_OSSEMUL */
diff --git a/ANDROID_3.4.5/sound/core/init.c b/ANDROID_3.4.5/sound/core/init.c
deleted file mode 100644
index 7b012d15..00000000
--- a/ANDROID_3.4.5/sound/core/init.c
+++ /dev/null
@@ -1,991 +0,0 @@
-/*
- * Initialization routines
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/file.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/ctype.h>
-#include <linux/pm.h>
-
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/info.h>
-
-/* monitor files for graceful shutdown (hotplug) */
-struct snd_monitor_file {
- struct file *file;
- const struct file_operations *disconnected_f_op;
- struct list_head shutdown_list; /* still need to shutdown */
- struct list_head list; /* link of monitor files */
-};
-
-static DEFINE_SPINLOCK(shutdown_lock);
-static LIST_HEAD(shutdown_files);
-
-static const struct file_operations snd_shutdown_f_ops;
-
-static unsigned int snd_cards_lock; /* locked for registering/using */
-struct snd_card *snd_cards[SNDRV_CARDS];
-EXPORT_SYMBOL(snd_cards);
-
-static DEFINE_MUTEX(snd_card_mutex);
-
-static char *slots[SNDRV_CARDS];
-module_param_array(slots, charp, NULL, 0444);
-MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
-
-/* return non-zero if the given index is reserved for the given
- * module via slots option
- */
-static int module_slot_match(struct module *module, int idx)
-{
- int match = 1;
-#ifdef MODULE
- const char *s1, *s2;
-
- if (!module || !module->name || !slots[idx])
- return 0;
-
- s1 = module->name;
- s2 = slots[idx];
- if (*s2 == '!') {
- match = 0; /* negative match */
- s2++;
- }
- /* compare module name strings
- * hyphens are handled as equivalent with underscore
- */
- for (;;) {
- char c1 = *s1++;
- char c2 = *s2++;
- if (c1 == '-')
- c1 = '_';
- if (c2 == '-')
- c2 = '_';
- if (c1 != c2)
- return !match;
- if (!c1)
- break;
- }
-#endif /* MODULE */
- return match;
-}
-
-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
-int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
-EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
-#endif
-
-#ifdef CONFIG_PROC_FS
-static void snd_card_id_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- snd_iprintf(buffer, "%s\n", entry->card->id);
-}
-
-static inline int init_info_for_card(struct snd_card *card)
-{
- int err;
- struct snd_info_entry *entry;
-
- if ((err = snd_info_card_register(card)) < 0) {
- snd_printd("unable to create card info\n");
- return err;
- }
- if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) {
- snd_printd("unable to create card entry\n");
- return err;
- }
- entry->c.text.read = snd_card_id_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- card->proc_id = entry;
- return 0;
-}
-#else /* !CONFIG_PROC_FS */
-#define init_info_for_card(card)
-#endif
-
-/**
- * snd_card_create - create and initialize a soundcard structure
- * @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
- * @xid: card identification (ASCII string)
- * @module: top level module for locking
- * @extra_size: allocate this extra size after the main soundcard structure
- * @card_ret: the pointer to store the created card instance
- *
- * Creates and initializes a soundcard structure.
- *
- * The function allocates snd_card instance via kzalloc with the given
- * space for the driver to use freely. The allocated struct is stored
- * in the given card_ret pointer.
- *
- * Returns zero if successful or a negative error code.
- */
-int snd_card_create(int idx, const char *xid,
- struct module *module, int extra_size,
- struct snd_card **card_ret)
-{
- struct snd_card *card;
- int err, idx2;
-
- if (snd_BUG_ON(!card_ret))
- return -EINVAL;
- *card_ret = NULL;
-
- if (extra_size < 0)
- extra_size = 0;
- card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
- if (!card)
- return -ENOMEM;
- if (xid)
- strlcpy(card->id, xid, sizeof(card->id));
- err = 0;
- mutex_lock(&snd_card_mutex);
- if (idx < 0) {
- for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
- /* idx == -1 == 0xffff means: take any free slot */
- if (~snd_cards_lock & idx & 1<<idx2) {
- if (module_slot_match(module, idx2)) {
- idx = idx2;
- break;
- }
- }
- }
- if (idx < 0) {
- for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
- /* idx == -1 == 0xffff means: take any free slot */
- if (~snd_cards_lock & idx & 1<<idx2) {
- if (!slots[idx2] || !*slots[idx2]) {
- idx = idx2;
- break;
- }
- }
- }
- if (idx < 0)
- err = -ENODEV;
- else if (idx < snd_ecards_limit) {
- if (snd_cards_lock & (1 << idx))
- err = -EBUSY; /* invalid */
- } else if (idx >= SNDRV_CARDS)
- err = -ENODEV;
- if (err < 0) {
- mutex_unlock(&snd_card_mutex);
- snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
- idx, snd_ecards_limit - 1, err);
- goto __error;
- }
- snd_cards_lock |= 1 << idx; /* lock it */
- if (idx >= snd_ecards_limit)
- snd_ecards_limit = idx + 1; /* increase the limit */
- mutex_unlock(&snd_card_mutex);
- card->number = idx;
- card->module = module;
- INIT_LIST_HEAD(&card->devices);
- init_rwsem(&card->controls_rwsem);
- rwlock_init(&card->ctl_files_rwlock);
- INIT_LIST_HEAD(&card->controls);
- INIT_LIST_HEAD(&card->ctl_files);
- spin_lock_init(&card->files_lock);
- INIT_LIST_HEAD(&card->files_list);
- init_waitqueue_head(&card->shutdown_sleep);
- atomic_set(&card->refcount, 0);
-#ifdef CONFIG_PM
- mutex_init(&card->power_lock);
- init_waitqueue_head(&card->power_sleep);
-#endif
- /* the control interface cannot be accessed from the user space until */
- /* snd_cards_bitmask and snd_cards are set with snd_card_register */
- err = snd_ctl_create(card);
- if (err < 0) {
- snd_printk(KERN_ERR "unable to register control minors\n");
- goto __error;
- }
- err = snd_info_card_create(card);
- if (err < 0) {
- snd_printk(KERN_ERR "unable to create card info\n");
- goto __error_ctl;
- }
- if (extra_size > 0)
- card->private_data = (char *)card + sizeof(struct snd_card);
- *card_ret = card;
- return 0;
-
- __error_ctl:
- snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
- __error:
- kfree(card);
- return err;
-}
-EXPORT_SYMBOL(snd_card_create);
-
-/* return non-zero if a card is already locked */
-int snd_card_locked(int card)
-{
- int locked;
-
- mutex_lock(&snd_card_mutex);
- locked = snd_cards_lock & (1 << card);
- mutex_unlock(&snd_card_mutex);
- return locked;
-}
-
-static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig)
-{
- return -ENODEV;
-}
-
-static ssize_t snd_disconnect_read(struct file *file, char __user *buf,
- size_t count, loff_t *offset)
-{
- return -ENODEV;
-}
-
-static ssize_t snd_disconnect_write(struct file *file, const char __user *buf,
- size_t count, loff_t *offset)
-{
- return -ENODEV;
-}
-
-static int snd_disconnect_release(struct inode *inode, struct file *file)
-{
- struct snd_monitor_file *df = NULL, *_df;
-
- spin_lock(&shutdown_lock);
- list_for_each_entry(_df, &shutdown_files, shutdown_list) {
- if (_df->file == file) {
- df = _df;
- list_del_init(&df->shutdown_list);
- break;
- }
- }
- spin_unlock(&shutdown_lock);
-
- if (likely(df)) {
- if ((file->f_flags & FASYNC) && df->disconnected_f_op->fasync)
- df->disconnected_f_op->fasync(-1, file, 0);
- return df->disconnected_f_op->release(inode, file);
- }
-
- panic("%s(%p, %p) failed!", __func__, inode, file);
-}
-
-static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
-{
- return POLLERR | POLLNVAL;
-}
-
-static long snd_disconnect_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -ENODEV;
-}
-
-static int snd_disconnect_mmap(struct file *file, struct vm_area_struct *vma)
-{
- return -ENODEV;
-}
-
-static int snd_disconnect_fasync(int fd, struct file *file, int on)
-{
- return -ENODEV;
-}
-
-static const struct file_operations snd_shutdown_f_ops =
-{
- .owner = THIS_MODULE,
- .llseek = snd_disconnect_llseek,
- .read = snd_disconnect_read,
- .write = snd_disconnect_write,
- .release = snd_disconnect_release,
- .poll = snd_disconnect_poll,
- .unlocked_ioctl = snd_disconnect_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = snd_disconnect_ioctl,
-#endif
- .mmap = snd_disconnect_mmap,
- .fasync = snd_disconnect_fasync
-};
-
-/**
- * snd_card_disconnect - disconnect all APIs from the file-operations (user space)
- * @card: soundcard structure
- *
- * Disconnects all APIs from the file-operations (user space).
- *
- * Returns zero, otherwise a negative error code.
- *
- * Note: The current implementation replaces all active file->f_op with special
- * dummy file operations (they do nothing except release).
- */
-int snd_card_disconnect(struct snd_card *card)
-{
- struct snd_monitor_file *mfile;
- int err;
-
- if (!card)
- return -EINVAL;
-
- spin_lock(&card->files_lock);
- if (card->shutdown) {
- spin_unlock(&card->files_lock);
- return 0;
- }
- card->shutdown = 1;
- spin_unlock(&card->files_lock);
-
- /* phase 1: disable fops (user space) operations for ALSA API */
- mutex_lock(&snd_card_mutex);
- snd_cards[card->number] = NULL;
- snd_cards_lock &= ~(1 << card->number);
- mutex_unlock(&snd_card_mutex);
-
- /* phase 2: replace file->f_op with special dummy operations */
-
- spin_lock(&card->files_lock);
- list_for_each_entry(mfile, &card->files_list, list) {
- /* it's critical part, use endless loop */
- /* we have no room to fail */
- mfile->disconnected_f_op = mfile->file->f_op;
-
- spin_lock(&shutdown_lock);
- list_add(&mfile->shutdown_list, &shutdown_files);
- spin_unlock(&shutdown_lock);
-
- mfile->file->f_op = &snd_shutdown_f_ops;
- fops_get(mfile->file->f_op);
- }
- spin_unlock(&card->files_lock);
-
- /* phase 3: notify all connected devices about disconnection */
- /* at this point, they cannot respond to any calls except release() */
-
-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
- if (snd_mixer_oss_notify_callback)
- snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT);
-#endif
-
- /* notify all devices that we are disconnected */
- err = snd_device_disconnect_all(card);
- if (err < 0)
- snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
-
- snd_info_card_disconnect(card);
- if (card->card_dev) {
- device_unregister(card->card_dev);
- card->card_dev = NULL;
- }
-#ifdef CONFIG_PM
- wake_up(&card->power_sleep);
-#endif
- return 0;
-}
-
-EXPORT_SYMBOL(snd_card_disconnect);
-
-/**
- * snd_card_free - frees given soundcard structure
- * @card: soundcard structure
- *
- * This function releases the soundcard structure and the all assigned
- * devices automatically. That is, you don't have to release the devices
- * by yourself.
- *
- * Returns zero. Frees all associated devices and frees the control
- * interface associated to given soundcard.
- */
-static int snd_card_do_free(struct snd_card *card)
-{
-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
- if (snd_mixer_oss_notify_callback)
- snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
-#endif
- if (snd_device_free_all(card, SNDRV_DEV_CMD_PRE) < 0) {
- snd_printk(KERN_ERR "unable to free all devices (pre)\n");
- /* Fatal, but this situation should never occur */
- }
- if (snd_device_free_all(card, SNDRV_DEV_CMD_NORMAL) < 0) {
- snd_printk(KERN_ERR "unable to free all devices (normal)\n");
- /* Fatal, but this situation should never occur */
- }
- if (snd_device_free_all(card, SNDRV_DEV_CMD_POST) < 0) {
- snd_printk(KERN_ERR "unable to free all devices (post)\n");
- /* Fatal, but this situation should never occur */
- }
- if (card->private_free)
- card->private_free(card);
- snd_info_free_entry(card->proc_id);
- if (snd_info_card_free(card) < 0) {
- snd_printk(KERN_WARNING "unable to free card info\n");
- /* Not fatal error */
- }
- kfree(card);
- return 0;
-}
-
-/**
- * snd_card_unref - release the reference counter
- * @card: the card instance
- *
- * Decrements the reference counter. When it reaches to zero, wake up
- * the sleeper and call the destructor if needed.
- */
-void snd_card_unref(struct snd_card *card)
-{
- if (atomic_dec_and_test(&card->refcount)) {
- wake_up(&card->shutdown_sleep);
- if (card->free_on_last_close)
- snd_card_do_free(card);
- }
-}
-EXPORT_SYMBOL(snd_card_unref);
-
-int snd_card_free_when_closed(struct snd_card *card)
-{
- int ret;
-
- atomic_inc(&card->refcount);
- ret = snd_card_disconnect(card);
- if (ret) {
- atomic_dec(&card->refcount);
- return ret;
- }
-
- card->free_on_last_close = 1;
- if (atomic_dec_and_test(&card->refcount))
- snd_card_do_free(card);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_card_free_when_closed);
-
-int snd_card_free(struct snd_card *card)
-{
- int ret = snd_card_disconnect(card);
- if (ret)
- return ret;
-
- /* wait, until all devices are ready for the free operation */
- wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));
- snd_card_do_free(card);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_card_free);
-
-/* retrieve the last word of shortname or longname */
-static const char *retrieve_id_from_card_name(const char *name)
-{
- const char *spos = name;
-
- while (*name) {
- if (isspace(*name) && isalnum(name[1]))
- spos = name + 1;
- name++;
- }
- return spos;
-}
-
-/* return true if the given id string doesn't conflict any other card ids */
-static bool card_id_ok(struct snd_card *card, const char *id)
-{
- int i;
- if (!snd_info_check_reserved_words(id))
- return false;
- for (i = 0; i < snd_ecards_limit; i++) {
- if (snd_cards[i] && snd_cards[i] != card &&
- !strcmp(snd_cards[i]->id, id))
- return false;
- }
- return true;
-}
-
-/* copy to card->id only with valid letters from nid */
-static void copy_valid_id_string(struct snd_card *card, const char *src,
- const char *nid)
-{
- char *id = card->id;
-
- while (*nid && !isalnum(*nid))
- nid++;
- if (isdigit(*nid))
- *id++ = isalpha(*src) ? *src : 'D';
- while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
- if (isalnum(*nid))
- *id++ = *nid;
- nid++;
- }
- *id = 0;
-}
-
-/* Set card->id from the given string
- * If the string conflicts with other ids, add a suffix to make it unique.
- */
-static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
- const char *nid)
-{
- int len, loops;
- bool with_suffix;
- bool is_default = false;
- char *id;
-
- copy_valid_id_string(card, src, nid);
- id = card->id;
-
- again:
- /* use "Default" for obviously invalid strings
- * ("card" conflicts with proc directories)
- */
- if (!*id || !strncmp(id, "card", 4)) {
- strcpy(id, "Default");
- is_default = true;
- }
-
- with_suffix = false;
- for (loops = 0; loops < SNDRV_CARDS; loops++) {
- if (card_id_ok(card, id))
- return; /* OK */
-
- len = strlen(id);
- if (!with_suffix) {
- /* add the "_X" suffix */
- char *spos = id + len;
- if (len > sizeof(card->id) - 3)
- spos = id + sizeof(card->id) - 3;
- strcpy(spos, "_1");
- with_suffix = true;
- } else {
- /* modify the existing suffix */
- if (id[len - 1] != '9')
- id[len - 1]++;
- else
- id[len - 1] = 'A';
- }
- }
- /* fallback to the default id */
- if (!is_default) {
- *id = 0;
- goto again;
- }
- /* last resort... */
- snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
- if (card->proc_root->name)
- strcpy(card->id, card->proc_root->name);
-}
-
-/**
- * snd_card_set_id - set card identification name
- * @card: soundcard structure
- * @nid: new identification string
- *
- * This function sets the card identification and checks for name
- * collisions.
- */
-void snd_card_set_id(struct snd_card *card, const char *nid)
-{
- /* check if user specified own card->id */
- if (card->id[0] != '\0')
- return;
- mutex_lock(&snd_card_mutex);
- snd_card_set_id_no_lock(card, nid, nid);
- mutex_unlock(&snd_card_mutex);
-}
-EXPORT_SYMBOL(snd_card_set_id);
-
-static ssize_t
-card_id_show_attr(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%s\n", card ? card->id : "(null)");
-}
-
-static ssize_t
-card_id_store_attr(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- char buf1[sizeof(card->id)];
- size_t copy = count > sizeof(card->id) - 1 ?
- sizeof(card->id) - 1 : count;
- size_t idx;
- int c;
-
- for (idx = 0; idx < copy; idx++) {
- c = buf[idx];
- if (!isalnum(c) && c != '_' && c != '-')
- return -EINVAL;
- }
- memcpy(buf1, buf, copy);
- buf1[copy] = '\0';
- mutex_lock(&snd_card_mutex);
- if (!card_id_ok(NULL, buf1)) {
- mutex_unlock(&snd_card_mutex);
- return -EEXIST;
- }
- strcpy(card->id, buf1);
- snd_info_card_id_change(card);
- mutex_unlock(&snd_card_mutex);
-
- return count;
-}
-
-static struct device_attribute card_id_attrs =
- __ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr);
-
-static ssize_t
-card_number_show_attr(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%i\n", card ? card->number : -1);
-}
-
-static struct device_attribute card_number_attrs =
- __ATTR(number, S_IRUGO, card_number_show_attr, NULL);
-
-/**
- * snd_card_register - register the soundcard
- * @card: soundcard structure
- *
- * This function registers all the devices assigned to the soundcard.
- * Until calling this, the ALSA control interface is blocked from the
- * external accesses. Thus, you should call this function at the end
- * of the initialization of the card.
- *
- * Returns zero otherwise a negative error code if the registration failed.
- */
-int snd_card_register(struct snd_card *card)
-{
- int err;
-
- if (snd_BUG_ON(!card))
- return -EINVAL;
-
- if (!card->card_dev) {
- card->card_dev = device_create(sound_class, card->dev,
- MKDEV(0, 0), card,
- "card%i", card->number);
- if (IS_ERR(card->card_dev))
- card->card_dev = NULL;
- }
-
- if ((err = snd_device_register_all(card)) < 0)
- return err;
- mutex_lock(&snd_card_mutex);
- if (snd_cards[card->number]) {
- /* already registered */
- mutex_unlock(&snd_card_mutex);
- return 0;
- }
- if (*card->id) {
- /* make a unique id name from the given string */
- char tmpid[sizeof(card->id)];
- memcpy(tmpid, card->id, sizeof(card->id));
- snd_card_set_id_no_lock(card, tmpid, tmpid);
- } else {
- /* create an id from either shortname or longname */
- const char *src;
- src = *card->shortname ? card->shortname : card->longname;
- snd_card_set_id_no_lock(card, src,
- retrieve_id_from_card_name(src));
- }
- snd_cards[card->number] = card;
- mutex_unlock(&snd_card_mutex);
- init_info_for_card(card);
-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
- if (snd_mixer_oss_notify_callback)
- snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
-#endif
- if (card->card_dev) {
- err = device_create_file(card->card_dev, &card_id_attrs);
- if (err < 0)
- return err;
- err = device_create_file(card->card_dev, &card_number_attrs);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-EXPORT_SYMBOL(snd_card_register);
-
-#ifdef CONFIG_PROC_FS
-static struct snd_info_entry *snd_card_info_entry;
-
-static void snd_card_info_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- int idx, count;
- struct snd_card *card;
-
- for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
- mutex_lock(&snd_card_mutex);
- if ((card = snd_cards[idx]) != NULL) {
- count++;
- snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
- idx,
- card->id,
- card->driver,
- card->shortname);
- snd_iprintf(buffer, " %s\n",
- card->longname);
- }
- mutex_unlock(&snd_card_mutex);
- }
- if (!count)
- snd_iprintf(buffer, "--- no soundcards ---\n");
-}
-
-#ifdef CONFIG_SND_OSSEMUL
-
-void snd_card_info_read_oss(struct snd_info_buffer *buffer)
-{
- int idx, count;
- struct snd_card *card;
-
- for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
- mutex_lock(&snd_card_mutex);
- if ((card = snd_cards[idx]) != NULL) {
- count++;
- snd_iprintf(buffer, "%s\n", card->longname);
- }
- mutex_unlock(&snd_card_mutex);
- }
- if (!count) {
- snd_iprintf(buffer, "--- no soundcards ---\n");
- }
-}
-
-#endif
-
-#ifdef MODULE
-static struct snd_info_entry *snd_card_module_info_entry;
-static void snd_card_module_info_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- int idx;
- struct snd_card *card;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++) {
- mutex_lock(&snd_card_mutex);
- if ((card = snd_cards[idx]) != NULL)
- snd_iprintf(buffer, "%2i %s\n",
- idx, card->module->name);
- mutex_unlock(&snd_card_mutex);
- }
-}
-#endif
-
-int __init snd_card_info_init(void)
-{
- struct snd_info_entry *entry;
-
- entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL);
- if (! entry)
- return -ENOMEM;
- entry->c.text.read = snd_card_info_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
- snd_card_info_entry = entry;
-
-#ifdef MODULE
- entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL);
- if (entry) {
- entry->c.text.read = snd_card_module_info_read;
- if (snd_info_register(entry) < 0)
- snd_info_free_entry(entry);
- else
- snd_card_module_info_entry = entry;
- }
-#endif
-
- return 0;
-}
-
-int __exit snd_card_info_done(void)
-{
- snd_info_free_entry(snd_card_info_entry);
-#ifdef MODULE
- snd_info_free_entry(snd_card_module_info_entry);
-#endif
- return 0;
-}
-
-#endif /* CONFIG_PROC_FS */
-
-/**
- * snd_component_add - add a component string
- * @card: soundcard structure
- * @component: the component id string
- *
- * This function adds the component id string to the supported list.
- * The component can be referred from the alsa-lib.
- *
- * Returns zero otherwise a negative error code.
- */
-
-int snd_component_add(struct snd_card *card, const char *component)
-{
- char *ptr;
- int len = strlen(component);
-
- ptr = strstr(card->components, component);
- if (ptr != NULL) {
- if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */
- return 1;
- }
- if (strlen(card->components) + 1 + len + 1 > sizeof(card->components)) {
- snd_BUG();
- return -ENOMEM;
- }
- if (card->components[0] != '\0')
- strcat(card->components, " ");
- strcat(card->components, component);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_component_add);
-
-/**
- * snd_card_file_add - add the file to the file list of the card
- * @card: soundcard structure
- * @file: file pointer
- *
- * This function adds the file to the file linked-list of the card.
- * This linked-list is used to keep tracking the connection state,
- * and to avoid the release of busy resources by hotplug.
- *
- * Returns zero or a negative error code.
- */
-int snd_card_file_add(struct snd_card *card, struct file *file)
-{
- struct snd_monitor_file *mfile;
-
- mfile = kmalloc(sizeof(*mfile), GFP_KERNEL);
- if (mfile == NULL)
- return -ENOMEM;
- mfile->file = file;
- mfile->disconnected_f_op = NULL;
- INIT_LIST_HEAD(&mfile->shutdown_list);
- spin_lock(&card->files_lock);
- if (card->shutdown) {
- spin_unlock(&card->files_lock);
- kfree(mfile);
- return -ENODEV;
- }
- list_add(&mfile->list, &card->files_list);
- atomic_inc(&card->refcount);
- spin_unlock(&card->files_lock);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_card_file_add);
-
-/**
- * snd_card_file_remove - remove the file from the file list
- * @card: soundcard structure
- * @file: file pointer
- *
- * This function removes the file formerly added to the card via
- * snd_card_file_add() function.
- * If all files are removed and snd_card_free_when_closed() was
- * called beforehand, it processes the pending release of
- * resources.
- *
- * Returns zero or a negative error code.
- */
-int snd_card_file_remove(struct snd_card *card, struct file *file)
-{
- struct snd_monitor_file *mfile, *found = NULL;
-
- spin_lock(&card->files_lock);
- list_for_each_entry(mfile, &card->files_list, list) {
- if (mfile->file == file) {
- list_del(&mfile->list);
- spin_lock(&shutdown_lock);
- list_del(&mfile->shutdown_list);
- spin_unlock(&shutdown_lock);
- if (mfile->disconnected_f_op)
- fops_put(mfile->disconnected_f_op);
- found = mfile;
- break;
- }
- }
- spin_unlock(&card->files_lock);
- if (!found) {
- snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
- return -ENOENT;
- }
- kfree(found);
- snd_card_unref(card);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_card_file_remove);
-
-#ifdef CONFIG_PM
-/**
- * snd_power_wait - wait until the power-state is changed.
- * @card: soundcard structure
- * @power_state: expected power state
- *
- * Waits until the power-state is changed.
- *
- * Note: the power lock must be active before call.
- */
-int snd_power_wait(struct snd_card *card, unsigned int power_state)
-{
- wait_queue_t wait;
- int result = 0;
-
- /* fastpath */
- if (snd_power_get_state(card) == power_state)
- return 0;
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&card->power_sleep, &wait);
- while (1) {
- if (card->shutdown) {
- result = -ENODEV;
- break;
- }
- if (snd_power_get_state(card) == power_state)
- break;
- set_current_state(TASK_UNINTERRUPTIBLE);
- snd_power_unlock(card);
- schedule_timeout(30 * HZ);
- snd_power_lock(card);
- }
- remove_wait_queue(&card->power_sleep, &wait);
- return result;
-}
-
-EXPORT_SYMBOL(snd_power_wait);
-#endif /* CONFIG_PM */
diff --git a/ANDROID_3.4.5/sound/core/isadma.c b/ANDROID_3.4.5/sound/core/isadma.c
deleted file mode 100644
index c0f1208b..00000000
--- a/ANDROID_3.4.5/sound/core/isadma.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * ISA DMA support functions
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/*
- * Defining following add some delay. Maybe this helps for some broken
- * ISA DMA controllers.
- */
-
-#undef HAVE_REALLY_SLOW_DMA_CONTROLLER
-
-#include <linux/export.h>
-#include <sound/core.h>
-#include <asm/dma.h>
-
-/**
- * snd_dma_program - program an ISA DMA transfer
- * @dma: the dma number
- * @addr: the physical address of the buffer
- * @size: the DMA transfer size
- * @mode: the DMA transfer mode, DMA_MODE_XXX
- *
- * Programs an ISA DMA transfer for the given buffer.
- */
-void snd_dma_program(unsigned long dma,
- unsigned long addr, unsigned int size,
- unsigned short mode)
-{
- unsigned long flags;
-
- flags = claim_dma_lock();
- disable_dma(dma);
- clear_dma_ff(dma);
- set_dma_mode(dma, mode);
- set_dma_addr(dma, addr);
- set_dma_count(dma, size);
- if (!(mode & DMA_MODE_NO_ENABLE))
- enable_dma(dma);
- release_dma_lock(flags);
-}
-
-EXPORT_SYMBOL(snd_dma_program);
-
-/**
- * snd_dma_disable - stop the ISA DMA transfer
- * @dma: the dma number
- *
- * Stops the ISA DMA transfer.
- */
-void snd_dma_disable(unsigned long dma)
-{
- unsigned long flags;
-
- flags = claim_dma_lock();
- clear_dma_ff(dma);
- disable_dma(dma);
- release_dma_lock(flags);
-}
-
-EXPORT_SYMBOL(snd_dma_disable);
-
-/**
- * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes
- * @dma: the dma number
- * @size: the dma transfer size
- *
- * Returns the current pointer in DMA tranfer buffer in bytes
- */
-unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
-{
- unsigned long flags;
- unsigned int result, result1;
-
- flags = claim_dma_lock();
- clear_dma_ff(dma);
- if (!isa_dma_bridge_buggy)
- disable_dma(dma);
- result = get_dma_residue(dma);
- /*
- * HACK - read the counter again and choose higher value in order to
- * avoid reading during counter lower byte roll over if the
- * isa_dma_bridge_buggy is set.
- */
- result1 = get_dma_residue(dma);
- if (!isa_dma_bridge_buggy)
- enable_dma(dma);
- release_dma_lock(flags);
- if (unlikely(result < result1))
- result = result1;
-#ifdef CONFIG_SND_DEBUG
- if (result > size)
- snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size);
-#endif
- if (result >= size || result == 0)
- return 0;
- else
- return size - result;
-}
-
-EXPORT_SYMBOL(snd_dma_pointer);
diff --git a/ANDROID_3.4.5/sound/core/jack.c b/ANDROID_3.4.5/sound/core/jack.c
deleted file mode 100644
index 471e1e3b..00000000
--- a/ANDROID_3.4.5/sound/core/jack.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Jack abstraction layer
- *
- * Copyright 2008 Wolfson Microelectronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/jack.h>
-#include <sound/core.h>
-
-static int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
- SW_HEADPHONE_INSERT,
- SW_MICROPHONE_INSERT,
- SW_LINEOUT_INSERT,
- SW_JACK_PHYSICAL_INSERT,
- SW_VIDEOOUT_INSERT,
- SW_LINEIN_INSERT,
-};
-
-static int snd_jack_dev_free(struct snd_device *device)
-{
- struct snd_jack *jack = device->device_data;
-
- if (jack->private_free)
- jack->private_free(jack);
-
- /* If the input device is registered with the input subsystem
- * then we need to use a different deallocator. */
- if (jack->registered)
- input_unregister_device(jack->input_dev);
- else
- input_free_device(jack->input_dev);
-
- kfree(jack->id);
- kfree(jack);
-
- return 0;
-}
-
-static int snd_jack_dev_register(struct snd_device *device)
-{
- struct snd_jack *jack = device->device_data;
- struct snd_card *card = device->card;
- int err, i;
-
- snprintf(jack->name, sizeof(jack->name), "%s %s",
- card->shortname, jack->id);
- jack->input_dev->name = jack->name;
-
- /* Default to the sound card device. */
- if (!jack->input_dev->dev.parent)
- jack->input_dev->dev.parent = snd_card_get_device_link(card);
-
- /* Add capabilities for any keys that are enabled */
- for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
- int testbit = SND_JACK_BTN_0 >> i;
-
- if (!(jack->type & testbit))
- continue;
-
- if (!jack->key[i])
- jack->key[i] = BTN_0 + i;
-
- input_set_capability(jack->input_dev, EV_KEY, jack->key[i]);
- }
-
- err = input_register_device(jack->input_dev);
- if (err == 0)
- jack->registered = 1;
-
- return err;
-}
-
-/**
- * snd_jack_new - Create a new jack
- * @card: the card instance
- * @id: an identifying string for this jack
- * @type: a bitmask of enum snd_jack_type values that can be detected by
- * this jack
- * @jjack: Used to provide the allocated jack object to the caller.
- *
- * Creates a new jack object.
- *
- * Returns zero if successful, or a negative error code on failure.
- * On success jjack will be initialised.
- */
-int snd_jack_new(struct snd_card *card, const char *id, int type,
- struct snd_jack **jjack)
-{
- struct snd_jack *jack;
- int err;
- int i;
- static struct snd_device_ops ops = {
- .dev_free = snd_jack_dev_free,
- .dev_register = snd_jack_dev_register,
- };
-
- jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL);
- if (jack == NULL)
- return -ENOMEM;
-
- jack->id = kstrdup(id, GFP_KERNEL);
-
- jack->input_dev = input_allocate_device();
- if (jack->input_dev == NULL) {
- err = -ENOMEM;
- goto fail_input;
- }
-
- jack->input_dev->phys = "ALSA";
-
- jack->type = type;
-
- for (i = 0; i < SND_JACK_SWITCH_TYPES; i++)
- if (type & (1 << i))
- input_set_capability(jack->input_dev, EV_SW,
- jack_switch_types[i]);
-
- err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
- if (err < 0)
- goto fail_input;
-
- *jjack = jack;
-
- return 0;
-
-fail_input:
- input_free_device(jack->input_dev);
- kfree(jack->id);
- kfree(jack);
- return err;
-}
-EXPORT_SYMBOL(snd_jack_new);
-
-/**
- * snd_jack_set_parent - Set the parent device for a jack
- *
- * @jack: The jack to configure
- * @parent: The device to set as parent for the jack.
- *
- * Set the parent for the jack input device in the device tree. This
- * function is only valid prior to registration of the jack. If no
- * parent is configured then the parent device will be the sound card.
- */
-void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
-{
- WARN_ON(jack->registered);
-
- jack->input_dev->dev.parent = parent;
-}
-EXPORT_SYMBOL(snd_jack_set_parent);
-
-/**
- * snd_jack_set_key - Set a key mapping on a jack
- *
- * @jack: The jack to configure
- * @type: Jack report type for this key
- * @keytype: Input layer key type to be reported
- *
- * Map a SND_JACK_BTN_ button type to an input layer key, allowing
- * reporting of keys on accessories via the jack abstraction. If no
- * mapping is provided but keys are enabled in the jack type then
- * BTN_n numeric buttons will be reported.
- *
- * Note that this is intended to be use by simple devices with small
- * numbers of keys that can be reported. It is also possible to
- * access the input device directly - devices with complex input
- * capabilities on accessories should consider doing this rather than
- * using this abstraction.
- *
- * This function may only be called prior to registration of the jack.
- */
-int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
- int keytype)
-{
- int key = fls(SND_JACK_BTN_0) - fls(type);
-
- WARN_ON(jack->registered);
-
- if (!keytype || key >= ARRAY_SIZE(jack->key))
- return -EINVAL;
-
- jack->type |= type;
- jack->key[key] = keytype;
-
- return 0;
-}
-EXPORT_SYMBOL(snd_jack_set_key);
-
-/**
- * snd_jack_report - Report the current status of a jack
- *
- * @jack: The jack to report status for
- * @status: The current status of the jack
- */
-void snd_jack_report(struct snd_jack *jack, int status)
-{
- int i;
-
- if (!jack)
- return;
-
- for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
- int testbit = SND_JACK_BTN_0 >> i;
-
- if (jack->type & testbit)
- input_report_key(jack->input_dev, jack->key[i],
- status & testbit);
- }
-
- for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
- int testbit = 1 << i;
- if (jack->type & testbit)
- input_report_switch(jack->input_dev,
- jack_switch_types[i],
- status & testbit);
- }
-
- input_sync(jack->input_dev);
-}
-EXPORT_SYMBOL(snd_jack_report);
-
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_DESCRIPTION("Jack detection support for ALSA");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/sound/core/memalloc.c b/ANDROID_3.4.5/sound/core/memalloc.c
deleted file mode 100644
index 69156923..00000000
--- a/ANDROID_3.4.5/sound/core/memalloc.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- * Takashi Iwai <tiwai@suse.de>
- *
- * Generic memory allocators
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <asm/uaccess.h>
-#include <linux/dma-mapping.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
-#include <sound/memalloc.h>
-
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Memory allocator for ALSA system.");
-MODULE_LICENSE("GPL");
-
-
-/*
- */
-
-static DEFINE_MUTEX(list_mutex);
-static LIST_HEAD(mem_list_head);
-
-/* buffer preservation list */
-struct snd_mem_list {
- struct snd_dma_buffer buffer;
- unsigned int id;
- struct list_head list;
-};
-
-/* id for pre-allocated buffers */
-#define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1
-
-/*
- *
- * Generic memory allocators
- *
- */
-
-static long snd_allocated_pages; /* holding the number of allocated pages */
-
-static inline void inc_snd_pages(int order)
-{
- snd_allocated_pages += 1 << order;
-}
-
-static inline void dec_snd_pages(int order)
-{
- snd_allocated_pages -= 1 << order;
-}
-
-/**
- * snd_malloc_pages - allocate pages with the given size
- * @size: the size to allocate in bytes
- * @gfp_flags: the allocation conditions, GFP_XXX
- *
- * Allocates the physically contiguous pages with the given size.
- *
- * Returns the pointer of the buffer, or NULL if no enoguh memory.
- */
-void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
-{
- int pg;
- void *res;
-
- if (WARN_ON(!size))
- return NULL;
- if (WARN_ON(!gfp_flags))
- return NULL;
- gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */
- pg = get_order(size);
- if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL)
- inc_snd_pages(pg);
- return res;
-}
-
-/**
- * snd_free_pages - release the pages
- * @ptr: the buffer pointer to release
- * @size: the allocated buffer size
- *
- * Releases the buffer allocated via snd_malloc_pages().
- */
-void snd_free_pages(void *ptr, size_t size)
-{
- int pg;
-
- if (ptr == NULL)
- return;
- pg = get_order(size);
- dec_snd_pages(pg);
- free_pages((unsigned long) ptr, pg);
-}
-
-/*
- *
- * Bus-specific memory allocators
- *
- */
-
-#ifdef CONFIG_HAS_DMA
-/* allocate the coherent DMA pages */
-static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
-{
- int pg;
- void *res;
- gfp_t gfp_flags;
-
- if (WARN_ON(!dma))
- return NULL;
- pg = get_order(size);
- gfp_flags = GFP_KERNEL
- | __GFP_COMP /* compound page lets parts be mapped */
- | __GFP_NORETRY /* don't trigger OOM-killer */
- | __GFP_NOWARN; /* no stack trace print - this call is non-critical */
- res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
- if (res != NULL)
- inc_snd_pages(pg);
-
- return res;
-}
-
-/* free the coherent DMA pages */
-static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
- dma_addr_t dma)
-{
- int pg;
-
- if (ptr == NULL)
- return;
- pg = get_order(size);
- dec_snd_pages(pg);
- dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
-}
-#endif /* CONFIG_HAS_DMA */
-
-/*
- *
- * ALSA generic memory management
- *
- */
-
-
-/**
- * snd_dma_alloc_pages - allocate the buffer area according to the given type
- * @type: the DMA buffer type
- * @device: the device pointer
- * @size: the buffer size to allocate
- * @dmab: buffer allocation record to store the allocated data
- *
- * Calls the memory-allocator function for the corresponding
- * buffer type.
- *
- * Returns zero if the buffer with the given size is allocated successfully,
- * other a negative value at error.
- */
-int snd_dma_alloc_pages(int type, struct device *device, size_t size,
- struct snd_dma_buffer *dmab)
-{
- if (WARN_ON(!size))
- return -ENXIO;
- if (WARN_ON(!dmab))
- return -ENXIO;
-
- dmab->dev.type = type;
- dmab->dev.dev = device;
- dmab->bytes = 0;
- switch (type) {
- case SNDRV_DMA_TYPE_CONTINUOUS:
- dmab->area = snd_malloc_pages(size,
- (__force gfp_t)(unsigned long)device);
- dmab->addr = 0;
- break;
-#ifdef CONFIG_HAS_DMA
- case SNDRV_DMA_TYPE_DEV:
- dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr);
- break;
-#endif
-#ifdef CONFIG_SND_DMA_SGBUF
- case SNDRV_DMA_TYPE_DEV_SG:
- snd_malloc_sgbuf_pages(device, size, dmab, NULL);
- break;
-#endif
- default:
- printk(KERN_ERR "snd-malloc: invalid device type %d\n", type);
- dmab->area = NULL;
- dmab->addr = 0;
- return -ENXIO;
- }
- if (! dmab->area)
- return -ENOMEM;
- dmab->bytes = size;
- return 0;
-}
-
-/**
- * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
- * @type: the DMA buffer type
- * @device: the device pointer
- * @size: the buffer size to allocate
- * @dmab: buffer allocation record to store the allocated data
- *
- * Calls the memory-allocator function for the corresponding
- * buffer type. When no space is left, this function reduces the size and
- * tries to allocate again. The size actually allocated is stored in
- * res_size argument.
- *
- * Returns zero if the buffer with the given size is allocated successfully,
- * other a negative value at error.
- */
-int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
- struct snd_dma_buffer *dmab)
-{
- int err;
-
- while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) {
- size_t aligned_size;
- if (err != -ENOMEM)
- return err;
- if (size <= PAGE_SIZE)
- return -ENOMEM;
- aligned_size = PAGE_SIZE << get_order(size);
- if (size != aligned_size)
- size = aligned_size;
- else
- size >>= 1;
- }
- if (! dmab->area)
- return -ENOMEM;
- return 0;
-}
-
-
-/**
- * snd_dma_free_pages - release the allocated buffer
- * @dmab: the buffer allocation record to release
- *
- * Releases the allocated buffer via snd_dma_alloc_pages().
- */
-void snd_dma_free_pages(struct snd_dma_buffer *dmab)
-{
- switch (dmab->dev.type) {
- case SNDRV_DMA_TYPE_CONTINUOUS:
- snd_free_pages(dmab->area, dmab->bytes);
- break;
-#ifdef CONFIG_HAS_DMA
- case SNDRV_DMA_TYPE_DEV:
- snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
- break;
-#endif
-#ifdef CONFIG_SND_DMA_SGBUF
- case SNDRV_DMA_TYPE_DEV_SG:
- snd_free_sgbuf_pages(dmab);
- break;
-#endif
- default:
- printk(KERN_ERR "snd-malloc: invalid device type %d\n", dmab->dev.type);
- }
-}
-
-
-/**
- * snd_dma_get_reserved - get the reserved buffer for the given device
- * @dmab: the buffer allocation record to store
- * @id: the buffer id
- *
- * Looks for the reserved-buffer list and re-uses if the same buffer
- * is found in the list. When the buffer is found, it's removed from the free list.
- *
- * Returns the size of buffer if the buffer is found, or zero if not found.
- */
-size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
-{
- struct snd_mem_list *mem;
-
- if (WARN_ON(!dmab))
- return 0;
-
- mutex_lock(&list_mutex);
- list_for_each_entry(mem, &mem_list_head, list) {
- if (mem->id == id &&
- (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
- ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
- struct device *dev = dmab->dev.dev;
- list_del(&mem->list);
- *dmab = mem->buffer;
- if (dmab->dev.dev == NULL)
- dmab->dev.dev = dev;
- kfree(mem);
- mutex_unlock(&list_mutex);
- return dmab->bytes;
- }
- }
- mutex_unlock(&list_mutex);
- return 0;
-}
-
-/**
- * snd_dma_reserve_buf - reserve the buffer
- * @dmab: the buffer to reserve
- * @id: the buffer id
- *
- * Reserves the given buffer as a reserved buffer.
- *
- * Returns zero if successful, or a negative code at error.
- */
-int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
-{
- struct snd_mem_list *mem;
-
- if (WARN_ON(!dmab))
- return -EINVAL;
- mem = kmalloc(sizeof(*mem), GFP_KERNEL);
- if (! mem)
- return -ENOMEM;
- mutex_lock(&list_mutex);
- mem->buffer = *dmab;
- mem->id = id;
- list_add_tail(&mem->list, &mem_list_head);
- mutex_unlock(&list_mutex);
- return 0;
-}
-
-/*
- * purge all reserved buffers
- */
-static void free_all_reserved_pages(void)
-{
- struct list_head *p;
- struct snd_mem_list *mem;
-
- mutex_lock(&list_mutex);
- while (! list_empty(&mem_list_head)) {
- p = mem_list_head.next;
- mem = list_entry(p, struct snd_mem_list, list);
- list_del(p);
- snd_dma_free_pages(&mem->buffer);
- kfree(mem);
- }
- mutex_unlock(&list_mutex);
-}
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * proc file interface
- */
-#define SND_MEM_PROC_FILE "driver/snd-page-alloc"
-static struct proc_dir_entry *snd_mem_proc;
-
-static int snd_mem_proc_read(struct seq_file *seq, void *offset)
-{
- long pages = snd_allocated_pages >> (PAGE_SHIFT-12);
- struct snd_mem_list *mem;
- int devno;
- static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" };
-
- mutex_lock(&list_mutex);
- seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n",
- pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
- devno = 0;
- list_for_each_entry(mem, &mem_list_head, list) {
- devno++;
- seq_printf(seq, "buffer %d : ID %08x : type %s\n",
- devno, mem->id, types[mem->buffer.dev.type]);
- seq_printf(seq, " addr = 0x%lx, size = %d bytes\n",
- (unsigned long)mem->buffer.addr,
- (int)mem->buffer.bytes);
- }
- mutex_unlock(&list_mutex);
- return 0;
-}
-
-static int snd_mem_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, snd_mem_proc_read, NULL);
-}
-
-/* FIXME: for pci only - other bus? */
-#ifdef CONFIG_PCI
-#define gettoken(bufp) strsep(bufp, " \t\n")
-
-static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer,
- size_t count, loff_t * ppos)
-{
- char buf[128];
- char *token, *p;
-
- if (count > sizeof(buf) - 1)
- return -EINVAL;
- if (copy_from_user(buf, buffer, count))
- return -EFAULT;
- buf[count] = '\0';
-
- p = buf;
- token = gettoken(&p);
- if (! token || *token == '#')
- return count;
- if (strcmp(token, "add") == 0) {
- char *endp;
- int vendor, device, size, buffers;
- long mask;
- int i, alloced;
- struct pci_dev *pci;
-
- if ((token = gettoken(&p)) == NULL ||
- (vendor = simple_strtol(token, NULL, 0)) <= 0 ||
- (token = gettoken(&p)) == NULL ||
- (device = simple_strtol(token, NULL, 0)) <= 0 ||
- (token = gettoken(&p)) == NULL ||
- (mask = simple_strtol(token, NULL, 0)) < 0 ||
- (token = gettoken(&p)) == NULL ||
- (size = memparse(token, &endp)) < 64*1024 ||
- size > 16*1024*1024 /* too big */ ||
- (token = gettoken(&p)) == NULL ||
- (buffers = simple_strtol(token, NULL, 0)) <= 0 ||
- buffers > 4) {
- printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
- return count;
- }
- vendor &= 0xffff;
- device &= 0xffff;
-
- alloced = 0;
- pci = NULL;
- while ((pci = pci_get_device(vendor, device, pci)) != NULL) {
- if (mask > 0 && mask < 0xffffffff) {
- if (pci_set_dma_mask(pci, mask) < 0 ||
- pci_set_consistent_dma_mask(pci, mask) < 0) {
- printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
- pci_dev_put(pci);
- return count;
- }
- }
- for (i = 0; i < buffers; i++) {
- struct snd_dma_buffer dmab;
- memset(&dmab, 0, sizeof(dmab));
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- size, &dmab) < 0) {
- printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
- pci_dev_put(pci);
- return count;
- }
- snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
- }
- alloced++;
- }
- if (! alloced) {
- for (i = 0; i < buffers; i++) {
- struct snd_dma_buffer dmab;
- memset(&dmab, 0, sizeof(dmab));
- /* FIXME: We can allocate only in ZONE_DMA
- * without a device pointer!
- */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
- size, &dmab) < 0) {
- printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
- break;
- }
- snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
- }
- }
- } else if (strcmp(token, "erase") == 0)
- /* FIXME: need for releasing each buffer chunk? */
- free_all_reserved_pages();
- else
- printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
- return count;
-}
-#endif /* CONFIG_PCI */
-
-static const struct file_operations snd_mem_proc_fops = {
- .owner = THIS_MODULE,
- .open = snd_mem_proc_open,
- .read = seq_read,
-#ifdef CONFIG_PCI
- .write = snd_mem_proc_write,
-#endif
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-#endif /* CONFIG_PROC_FS */
-
-/*
- * module entry
- */
-
-static int __init snd_mem_init(void)
-{
-#ifdef CONFIG_PROC_FS
- snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL,
- &snd_mem_proc_fops);
-#endif
- return 0;
-}
-
-static void __exit snd_mem_exit(void)
-{
- remove_proc_entry(SND_MEM_PROC_FILE, NULL);
- free_all_reserved_pages();
- if (snd_allocated_pages > 0)
- printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages);
-}
-
-
-module_init(snd_mem_init)
-module_exit(snd_mem_exit)
-
-
-/*
- * exports
- */
-EXPORT_SYMBOL(snd_dma_alloc_pages);
-EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
-EXPORT_SYMBOL(snd_dma_free_pages);
-
-EXPORT_SYMBOL(snd_dma_get_reserved_buf);
-EXPORT_SYMBOL(snd_dma_reserve_buf);
-
-EXPORT_SYMBOL(snd_malloc_pages);
-EXPORT_SYMBOL(snd_free_pages);
diff --git a/ANDROID_3.4.5/sound/core/memory.c b/ANDROID_3.4.5/sound/core/memory.c
deleted file mode 100644
index 66a278d0..00000000
--- a/ANDROID_3.4.5/sound/core/memory.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- * Misc memory accessors
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/export.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <sound/core.h>
-
-/**
- * copy_to_user_fromio - copy data from mmio-space to user-space
- * @dst: the destination pointer on user-space
- * @src: the source pointer on mmio
- * @count: the data size to copy in bytes
- *
- * Copies the data from mmio-space to user-space.
- *
- * Returns zero if successful, or non-zero on failure.
- */
-int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count)
-{
-#if defined(__i386__) || defined(CONFIG_SPARC32)
- return copy_to_user(dst, (const void __force*)src, count) ? -EFAULT : 0;
-#else
- char buf[256];
- while (count) {
- size_t c = count;
- if (c > sizeof(buf))
- c = sizeof(buf);
- memcpy_fromio(buf, (void __iomem *)src, c);
- if (copy_to_user(dst, buf, c))
- return -EFAULT;
- count -= c;
- dst += c;
- src += c;
- }
- return 0;
-#endif
-}
-
-EXPORT_SYMBOL(copy_to_user_fromio);
-
-/**
- * copy_from_user_toio - copy data from user-space to mmio-space
- * @dst: the destination pointer on mmio-space
- * @src: the source pointer on user-space
- * @count: the data size to copy in bytes
- *
- * Copies the data from user-space to mmio-space.
- *
- * Returns zero if successful, or non-zero on failure.
- */
-int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count)
-{
-#if defined(__i386__) || defined(CONFIG_SPARC32)
- return copy_from_user((void __force *)dst, src, count) ? -EFAULT : 0;
-#else
- char buf[256];
- while (count) {
- size_t c = count;
- if (c > sizeof(buf))
- c = sizeof(buf);
- if (copy_from_user(buf, src, c))
- return -EFAULT;
- memcpy_toio(dst, buf, c);
- count -= c;
- dst += c;
- src += c;
- }
- return 0;
-#endif
-}
-
-EXPORT_SYMBOL(copy_from_user_toio);
diff --git a/ANDROID_3.4.5/sound/core/misc.c b/ANDROID_3.4.5/sound/core/misc.c
deleted file mode 100644
index 76816792..00000000
--- a/ANDROID_3.4.5/sound/core/misc.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Misc and compatibility things
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/moduleparam.h>
-#include <linux/time.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <sound/core.h>
-
-#ifdef CONFIG_SND_DEBUG
-
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-#define DEFAULT_DEBUG_LEVEL 2
-#else
-#define DEFAULT_DEBUG_LEVEL 1
-#endif
-
-static int debug = DEFAULT_DEBUG_LEVEL;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0 = disable)");
-
-#endif /* CONFIG_SND_DEBUG */
-
-void release_and_free_resource(struct resource *res)
-{
- if (res) {
- release_resource(res);
- kfree(res);
- }
-}
-
-EXPORT_SYMBOL(release_and_free_resource);
-
-#ifdef CONFIG_SND_VERBOSE_PRINTK
-/* strip the leading path if the given path is absolute */
-static const char *sanity_file_name(const char *path)
-{
- if (*path == '/')
- return strrchr(path, '/') + 1;
- else
- return path;
-}
-#endif
-
-#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK)
-void __snd_printk(unsigned int level, const char *path, int line,
- const char *format, ...)
-{
- va_list args;
-#ifdef CONFIG_SND_VERBOSE_PRINTK
- struct va_format vaf;
- char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV";
-#endif
-
-#ifdef CONFIG_SND_DEBUG
- if (debug < level)
- return;
-#endif
-
- va_start(args, format);
-#ifdef CONFIG_SND_VERBOSE_PRINTK
- vaf.fmt = format;
- vaf.va = &args;
- if (format[0] == '<' && format[2] == '>') {
- memcpy(verbose_fmt, format, 3);
- vaf.fmt = format + 3;
- } else if (level)
- memcpy(verbose_fmt, KERN_DEBUG, 3);
- printk(verbose_fmt, sanity_file_name(path), line, &vaf);
-#else
- vprintk(format, args);
-#endif
- va_end(args);
-}
-EXPORT_SYMBOL_GPL(__snd_printk);
-#endif
-
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-/**
- * snd_pci_quirk_lookup_id - look up a PCI SSID quirk list
- * @vendor: PCI SSV id
- * @device: PCI SSD id
- * @list: quirk list, terminated by a null entry
- *
- * Look through the given quirk list and finds a matching entry
- * with the same PCI SSID. When subdevice is 0, all subdevice
- * values may match.
- *
- * Returns the matched entry pointer, or NULL if nothing matched.
- */
-const struct snd_pci_quirk *
-snd_pci_quirk_lookup_id(u16 vendor, u16 device,
- const struct snd_pci_quirk *list)
-{
- const struct snd_pci_quirk *q;
-
- for (q = list; q->subvendor; q++) {
- if (q->subvendor != vendor)
- continue;
- if (!q->subdevice ||
- (device & q->subdevice_mask) == q->subdevice)
- return q;
- }
- return NULL;
-}
-EXPORT_SYMBOL(snd_pci_quirk_lookup_id);
-
-/**
- * snd_pci_quirk_lookup - look up a PCI SSID quirk list
- * @pci: pci_dev handle
- * @list: quirk list, terminated by a null entry
- *
- * Look through the given quirk list and finds a matching entry
- * with the same PCI SSID. When subdevice is 0, all subdevice
- * values may match.
- *
- * Returns the matched entry pointer, or NULL if nothing matched.
- */
-const struct snd_pci_quirk *
-snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list)
-{
- return snd_pci_quirk_lookup_id(pci->subsystem_vendor,
- pci->subsystem_device,
- list);
-}
-EXPORT_SYMBOL(snd_pci_quirk_lookup);
-#endif
diff --git a/ANDROID_3.4.5/sound/core/oss/Makefile b/ANDROID_3.4.5/sound/core/oss/Makefile
deleted file mode 100644
index 10a79453..00000000
--- a/ANDROID_3.4.5/sound/core/oss/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Makefile for ALSA
-# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
-#
-
-snd-mixer-oss-objs := mixer_oss.o
-
-snd-pcm-oss-y := pcm_oss.o
-snd-pcm-oss-$(CONFIG_SND_PCM_OSS_PLUGINS) += pcm_plugin.o \
- io.o copy.o linear.o mulaw.o route.o rate.o
-
-obj-$(CONFIG_SND_MIXER_OSS) += snd-mixer-oss.o
-obj-$(CONFIG_SND_PCM_OSS) += snd-pcm-oss.o
diff --git a/ANDROID_3.4.5/sound/core/oss/copy.c b/ANDROID_3.4.5/sound/core/oss/copy.c
deleted file mode 100644
index 05b58d4f..00000000
--- a/ANDROID_3.4.5/sound/core/oss/copy.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Linear conversion Plug-In
- * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/time.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include "pcm_plugin.h"
-
-static snd_pcm_sframes_t copy_transfer(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- unsigned int channel;
- unsigned int nchannels;
-
- if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
- return -ENXIO;
- if (frames == 0)
- return 0;
- nchannels = plugin->src_format.channels;
- for (channel = 0; channel < nchannels; channel++) {
- if (snd_BUG_ON(src_channels->area.first % 8 ||
- src_channels->area.step % 8))
- return -ENXIO;
- if (snd_BUG_ON(dst_channels->area.first % 8 ||
- dst_channels->area.step % 8))
- return -ENXIO;
- if (!src_channels->enabled) {
- if (dst_channels->wanted)
- snd_pcm_area_silence(&dst_channels->area, 0, frames, plugin->dst_format.format);
- dst_channels->enabled = 0;
- continue;
- }
- dst_channels->enabled = 1;
- snd_pcm_area_copy(&src_channels->area, 0, &dst_channels->area, 0, frames, plugin->src_format.format);
- src_channels++;
- dst_channels++;
- }
- return frames;
-}
-
-int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin)
-{
- int err;
- struct snd_pcm_plugin *plugin;
- int width;
-
- if (snd_BUG_ON(!r_plugin))
- return -ENXIO;
- *r_plugin = NULL;
-
- if (snd_BUG_ON(src_format->format != dst_format->format))
- return -ENXIO;
- if (snd_BUG_ON(src_format->rate != dst_format->rate))
- return -ENXIO;
- if (snd_BUG_ON(src_format->channels != dst_format->channels))
- return -ENXIO;
-
- width = snd_pcm_format_physical_width(src_format->format);
- if (snd_BUG_ON(width <= 0))
- return -ENXIO;
-
- err = snd_pcm_plugin_build(plug, "copy", src_format, dst_format,
- 0, &plugin);
- if (err < 0)
- return err;
- plugin->transfer = copy_transfer;
- *r_plugin = plugin;
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/oss/io.c b/ANDROID_3.4.5/sound/core/oss/io.c
deleted file mode 100644
index 6faa1d71..00000000
--- a/ANDROID_3.4.5/sound/core/oss/io.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * PCM I/O Plug-In Interface
- * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/time.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include "pcm_plugin.h"
-
-#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
-#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1)
-#define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
-#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1)
-
-/*
- * Basic io plugin
- */
-
-static snd_pcm_sframes_t io_playback_transfer(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- if (snd_BUG_ON(!plugin))
- return -ENXIO;
- if (snd_BUG_ON(!src_channels))
- return -ENXIO;
- if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
- return pcm_write(plugin->plug, src_channels->area.addr, frames);
- } else {
- int channel, channels = plugin->dst_format.channels;
- void **bufs = (void**)plugin->extra_data;
- if (snd_BUG_ON(!bufs))
- return -ENXIO;
- for (channel = 0; channel < channels; channel++) {
- if (src_channels[channel].enabled)
- bufs[channel] = src_channels[channel].area.addr;
- else
- bufs[channel] = NULL;
- }
- return pcm_writev(plugin->plug, bufs, frames);
- }
-}
-
-static snd_pcm_sframes_t io_capture_transfer(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- if (snd_BUG_ON(!plugin))
- return -ENXIO;
- if (snd_BUG_ON(!dst_channels))
- return -ENXIO;
- if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
- return pcm_read(plugin->plug, dst_channels->area.addr, frames);
- } else {
- int channel, channels = plugin->dst_format.channels;
- void **bufs = (void**)plugin->extra_data;
- if (snd_BUG_ON(!bufs))
- return -ENXIO;
- for (channel = 0; channel < channels; channel++) {
- if (dst_channels[channel].enabled)
- bufs[channel] = dst_channels[channel].area.addr;
- else
- bufs[channel] = NULL;
- }
- return pcm_readv(plugin->plug, bufs, frames);
- }
- return 0;
-}
-
-static snd_pcm_sframes_t io_src_channels(struct snd_pcm_plugin *plugin,
- snd_pcm_uframes_t frames,
- struct snd_pcm_plugin_channel **channels)
-{
- int err;
- unsigned int channel;
- struct snd_pcm_plugin_channel *v;
- err = snd_pcm_plugin_client_channels(plugin, frames, &v);
- if (err < 0)
- return err;
- *channels = v;
- if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
- for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v)
- v->wanted = 1;
- }
- return frames;
-}
-
-int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug,
- struct snd_pcm_hw_params *params,
- struct snd_pcm_plugin **r_plugin)
-{
- int err;
- struct snd_pcm_plugin_format format;
- struct snd_pcm_plugin *plugin;
-
- if (snd_BUG_ON(!r_plugin))
- return -ENXIO;
- *r_plugin = NULL;
- if (snd_BUG_ON(!plug || !params))
- return -ENXIO;
- format.format = params_format(params);
- format.rate = params_rate(params);
- format.channels = params_channels(params);
- err = snd_pcm_plugin_build(plug, "I/O io",
- &format, &format,
- sizeof(void *) * format.channels,
- &plugin);
- if (err < 0)
- return err;
- plugin->access = params_access(params);
- if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) {
- plugin->transfer = io_playback_transfer;
- if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED)
- plugin->client_channels = io_src_channels;
- } else {
- plugin->transfer = io_capture_transfer;
- }
-
- *r_plugin = plugin;
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/oss/linear.c b/ANDROID_3.4.5/sound/core/oss/linear.c
deleted file mode 100644
index 2045697f..00000000
--- a/ANDROID_3.4.5/sound/core/oss/linear.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Linear conversion Plug-In
- * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>,
- * Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/time.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include "pcm_plugin.h"
-
-/*
- * Basic linear conversion plugin
- */
-
-struct linear_priv {
- int cvt_endian; /* need endian conversion? */
- unsigned int src_ofs; /* byte offset in source format */
- unsigned int dst_ofs; /* byte soffset in destination format */
- unsigned int copy_ofs; /* byte offset in temporary u32 data */
- unsigned int dst_bytes; /* byte size of destination format */
- unsigned int copy_bytes; /* bytes to copy per conversion */
- unsigned int flip; /* MSB flip for signeness, done after endian conv */
-};
-
-static inline void do_convert(struct linear_priv *data,
- unsigned char *dst, unsigned char *src)
-{
- unsigned int tmp = 0;
- unsigned char *p = (unsigned char *)&tmp;
-
- memcpy(p + data->copy_ofs, src + data->src_ofs, data->copy_bytes);
- if (data->cvt_endian)
- tmp = swab32(tmp);
- tmp ^= data->flip;
- memcpy(dst, p + data->dst_ofs, data->dst_bytes);
-}
-
-static void convert(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- struct linear_priv *data = (struct linear_priv *)plugin->extra_data;
- int channel;
- int nchannels = plugin->src_format.channels;
- for (channel = 0; channel < nchannels; ++channel) {
- char *src;
- char *dst;
- int src_step, dst_step;
- snd_pcm_uframes_t frames1;
- if (!src_channels[channel].enabled) {
- if (dst_channels[channel].wanted)
- snd_pcm_area_silence(&dst_channels[channel].area, 0, frames, plugin->dst_format.format);
- dst_channels[channel].enabled = 0;
- continue;
- }
- dst_channels[channel].enabled = 1;
- src = src_channels[channel].area.addr + src_channels[channel].area.first / 8;
- dst = dst_channels[channel].area.addr + dst_channels[channel].area.first / 8;
- src_step = src_channels[channel].area.step / 8;
- dst_step = dst_channels[channel].area.step / 8;
- frames1 = frames;
- while (frames1-- > 0) {
- do_convert(data, dst, src);
- src += src_step;
- dst += dst_step;
- }
- }
-}
-
-static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
- return -ENXIO;
- if (frames == 0)
- return 0;
-#ifdef CONFIG_SND_DEBUG
- {
- unsigned int channel;
- for (channel = 0; channel < plugin->src_format.channels; channel++) {
- if (snd_BUG_ON(src_channels[channel].area.first % 8 ||
- src_channels[channel].area.step % 8))
- return -ENXIO;
- if (snd_BUG_ON(dst_channels[channel].area.first % 8 ||
- dst_channels[channel].area.step % 8))
- return -ENXIO;
- }
- }
-#endif
- convert(plugin, src_channels, dst_channels, frames);
- return frames;
-}
-
-static void init_data(struct linear_priv *data,
- snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
-{
- int src_le, dst_le, src_bytes, dst_bytes;
-
- src_bytes = snd_pcm_format_width(src_format) / 8;
- dst_bytes = snd_pcm_format_width(dst_format) / 8;
- src_le = snd_pcm_format_little_endian(src_format) > 0;
- dst_le = snd_pcm_format_little_endian(dst_format) > 0;
-
- data->dst_bytes = dst_bytes;
- data->cvt_endian = src_le != dst_le;
- data->copy_bytes = src_bytes < dst_bytes ? src_bytes : dst_bytes;
- if (src_le) {
- data->copy_ofs = 4 - data->copy_bytes;
- data->src_ofs = src_bytes - data->copy_bytes;
- } else
- data->src_ofs = snd_pcm_format_physical_width(src_format) / 8 -
- src_bytes;
- if (dst_le)
- data->dst_ofs = 4 - data->dst_bytes;
- else
- data->dst_ofs = snd_pcm_format_physical_width(dst_format) / 8 -
- dst_bytes;
- if (snd_pcm_format_signed(src_format) !=
- snd_pcm_format_signed(dst_format)) {
- if (dst_le)
- data->flip = (__force u32)cpu_to_le32(0x80000000);
- else
- data->flip = (__force u32)cpu_to_be32(0x80000000);
- }
-}
-
-int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin)
-{
- int err;
- struct linear_priv *data;
- struct snd_pcm_plugin *plugin;
-
- if (snd_BUG_ON(!r_plugin))
- return -ENXIO;
- *r_plugin = NULL;
-
- if (snd_BUG_ON(src_format->rate != dst_format->rate))
- return -ENXIO;
- if (snd_BUG_ON(src_format->channels != dst_format->channels))
- return -ENXIO;
- if (snd_BUG_ON(!snd_pcm_format_linear(src_format->format) ||
- !snd_pcm_format_linear(dst_format->format)))
- return -ENXIO;
-
- err = snd_pcm_plugin_build(plug, "linear format conversion",
- src_format, dst_format,
- sizeof(struct linear_priv), &plugin);
- if (err < 0)
- return err;
- data = (struct linear_priv *)plugin->extra_data;
- init_data(data, src_format->format, dst_format->format);
- plugin->transfer = linear_transfer;
- *r_plugin = plugin;
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/oss/mixer_oss.c b/ANDROID_3.4.5/sound/core/oss/mixer_oss.c
deleted file mode 100644
index c3537688..00000000
--- a/ANDROID_3.4.5/sound/core/oss/mixer_oss.c
+++ /dev/null
@@ -1,1422 +0,0 @@
-/*
- * OSS emulation layer for the mixer interface
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <sound/control.h>
-#include <sound/info.h>
-#include <sound/mixer_oss.h>
-#include <linux/soundcard.h>
-
-#define OSS_ALSAEMULVER _SIOR ('M', 249, int)
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Mixer OSS emulation for ALSA.");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER);
-
-static int snd_mixer_oss_open(struct inode *inode, struct file *file)
-{
- struct snd_card *card;
- struct snd_mixer_oss_file *fmixer;
- int err;
-
- err = nonseekable_open(inode, file);
- if (err < 0)
- return err;
-
- card = snd_lookup_oss_minor_data(iminor(inode),
- SNDRV_OSS_DEVICE_TYPE_MIXER);
- if (card == NULL)
- return -ENODEV;
- if (card->mixer_oss == NULL) {
- snd_card_unref(card);
- return -ENODEV;
- }
- err = snd_card_file_add(card, file);
- if (err < 0) {
- snd_card_unref(card);
- return err;
- }
- fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
- if (fmixer == NULL) {
- snd_card_file_remove(card, file);
- snd_card_unref(card);
- return -ENOMEM;
- }
- fmixer->card = card;
- fmixer->mixer = card->mixer_oss;
- file->private_data = fmixer;
- if (!try_module_get(card->module)) {
- kfree(fmixer);
- snd_card_file_remove(card, file);
- snd_card_unref(card);
- return -EFAULT;
- }
- snd_card_unref(card);
- return 0;
-}
-
-static int snd_mixer_oss_release(struct inode *inode, struct file *file)
-{
- struct snd_mixer_oss_file *fmixer;
-
- if (file->private_data) {
- fmixer = file->private_data;
- module_put(fmixer->card->module);
- snd_card_file_remove(fmixer->card, file);
- kfree(fmixer);
- }
- return 0;
-}
-
-static int snd_mixer_oss_info(struct snd_mixer_oss_file *fmixer,
- mixer_info __user *_info)
-{
- struct snd_card *card = fmixer->card;
- struct snd_mixer_oss *mixer = fmixer->mixer;
- struct mixer_info info;
-
- memset(&info, 0, sizeof(info));
- strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
- strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
- info.modify_counter = card->mixer_oss_change_count;
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_mixer_oss_info_obsolete(struct snd_mixer_oss_file *fmixer,
- _old_mixer_info __user *_info)
-{
- struct snd_card *card = fmixer->card;
- struct snd_mixer_oss *mixer = fmixer->mixer;
- _old_mixer_info info;
-
- memset(&info, 0, sizeof(info));
- strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
- strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_mixer_oss_caps(struct snd_mixer_oss_file *fmixer)
-{
- struct snd_mixer_oss *mixer = fmixer->mixer;
- int result = 0;
-
- if (mixer == NULL)
- return -EIO;
- if (mixer->get_recsrc && mixer->put_recsrc)
- result |= SOUND_CAP_EXCL_INPUT;
- return result;
-}
-
-static int snd_mixer_oss_devmask(struct snd_mixer_oss_file *fmixer)
-{
- struct snd_mixer_oss *mixer = fmixer->mixer;
- struct snd_mixer_oss_slot *pslot;
- int result = 0, chn;
-
- if (mixer == NULL)
- return -EIO;
- for (chn = 0; chn < 31; chn++) {
- pslot = &mixer->slots[chn];
- if (pslot->put_volume || pslot->put_recsrc)
- result |= 1 << chn;
- }
- return result;
-}
-
-static int snd_mixer_oss_stereodevs(struct snd_mixer_oss_file *fmixer)
-{
- struct snd_mixer_oss *mixer = fmixer->mixer;
- struct snd_mixer_oss_slot *pslot;
- int result = 0, chn;
-
- if (mixer == NULL)
- return -EIO;
- for (chn = 0; chn < 31; chn++) {
- pslot = &mixer->slots[chn];
- if (pslot->put_volume && pslot->stereo)
- result |= 1 << chn;
- }
- return result;
-}
-
-static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer)
-{
- struct snd_mixer_oss *mixer = fmixer->mixer;
- int result = 0;
-
- if (mixer == NULL)
- return -EIO;
- if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */
- result = mixer->mask_recsrc;
- } else {
- struct snd_mixer_oss_slot *pslot;
- int chn;
- for (chn = 0; chn < 31; chn++) {
- pslot = &mixer->slots[chn];
- if (pslot->put_recsrc)
- result |= 1 << chn;
- }
- }
- return result;
-}
-
-static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer)
-{
- struct snd_mixer_oss *mixer = fmixer->mixer;
- int result = 0;
-
- if (mixer == NULL)
- return -EIO;
- if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */
- int err;
- unsigned int index;
- if ((err = mixer->get_recsrc(fmixer, &index)) < 0)
- return err;
- result = 1 << index;
- } else {
- struct snd_mixer_oss_slot *pslot;
- int chn;
- for (chn = 0; chn < 31; chn++) {
- pslot = &mixer->slots[chn];
- if (pslot->get_recsrc) {
- int active = 0;
- pslot->get_recsrc(fmixer, pslot, &active);
- if (active)
- result |= 1 << chn;
- }
- }
- }
- return mixer->oss_recsrc = result;
-}
-
-static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsrc)
-{
- struct snd_mixer_oss *mixer = fmixer->mixer;
- struct snd_mixer_oss_slot *pslot;
- int chn, active;
- unsigned int index;
- int result = 0;
-
- if (mixer == NULL)
- return -EIO;
- if (mixer->get_recsrc && mixer->put_recsrc) { /* exclusive input */
- if (recsrc & ~mixer->oss_recsrc)
- recsrc &= ~mixer->oss_recsrc;
- mixer->put_recsrc(fmixer, ffz(~recsrc));
- mixer->get_recsrc(fmixer, &index);
- result = 1 << index;
- }
- for (chn = 0; chn < 31; chn++) {
- pslot = &mixer->slots[chn];
- if (pslot->put_recsrc) {
- active = (recsrc & (1 << chn)) ? 1 : 0;
- pslot->put_recsrc(fmixer, pslot, active);
- }
- }
- if (! result) {
- for (chn = 0; chn < 31; chn++) {
- pslot = &mixer->slots[chn];
- if (pslot->get_recsrc) {
- active = 0;
- pslot->get_recsrc(fmixer, pslot, &active);
- if (active)
- result |= 1 << chn;
- }
- }
- }
- return result;
-}
-
-static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot)
-{
- struct snd_mixer_oss *mixer = fmixer->mixer;
- struct snd_mixer_oss_slot *pslot;
- int result = 0, left, right;
-
- if (mixer == NULL || slot > 30)
- return -EIO;
- pslot = &mixer->slots[slot];
- left = pslot->volume[0];
- right = pslot->volume[1];
- if (pslot->get_volume)
- result = pslot->get_volume(fmixer, pslot, &left, &right);
- if (!pslot->stereo)
- right = left;
- if (snd_BUG_ON(left < 0 || left > 100))
- return -EIO;
- if (snd_BUG_ON(right < 0 || right > 100))
- return -EIO;
- if (result >= 0) {
- pslot->volume[0] = left;
- pslot->volume[1] = right;
- result = (left & 0xff) | ((right & 0xff) << 8);
- }
- return result;
-}
-
-static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer,
- int slot, int volume)
-{
- struct snd_mixer_oss *mixer = fmixer->mixer;
- struct snd_mixer_oss_slot *pslot;
- int result = 0, left = volume & 0xff, right = (volume >> 8) & 0xff;
-
- if (mixer == NULL || slot > 30)
- return -EIO;
- pslot = &mixer->slots[slot];
- if (left > 100)
- left = 100;
- if (right > 100)
- right = 100;
- if (!pslot->stereo)
- right = left;
- if (pslot->put_volume)
- result = pslot->put_volume(fmixer, pslot, left, right);
- if (result < 0)
- return result;
- pslot->volume[0] = left;
- pslot->volume[1] = right;
- return (left & 0xff) | ((right & 0xff) << 8);
-}
-
-static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
- int tmp;
-
- if (snd_BUG_ON(!fmixer))
- return -ENXIO;
- if (((cmd >> 8) & 0xff) == 'M') {
- switch (cmd) {
- case SOUND_MIXER_INFO:
- return snd_mixer_oss_info(fmixer, argp);
- case SOUND_OLD_MIXER_INFO:
- return snd_mixer_oss_info_obsolete(fmixer, argp);
- case SOUND_MIXER_WRITE_RECSRC:
- if (get_user(tmp, p))
- return -EFAULT;
- tmp = snd_mixer_oss_set_recsrc(fmixer, tmp);
- if (tmp < 0)
- return tmp;
- return put_user(tmp, p);
- case OSS_GETVERSION:
- return put_user(SNDRV_OSS_VERSION, p);
- case OSS_ALSAEMULVER:
- return put_user(1, p);
- case SOUND_MIXER_READ_DEVMASK:
- tmp = snd_mixer_oss_devmask(fmixer);
- if (tmp < 0)
- return tmp;
- return put_user(tmp, p);
- case SOUND_MIXER_READ_STEREODEVS:
- tmp = snd_mixer_oss_stereodevs(fmixer);
- if (tmp < 0)
- return tmp;
- return put_user(tmp, p);
- case SOUND_MIXER_READ_RECMASK:
- tmp = snd_mixer_oss_recmask(fmixer);
- if (tmp < 0)
- return tmp;
- return put_user(tmp, p);
- case SOUND_MIXER_READ_CAPS:
- tmp = snd_mixer_oss_caps(fmixer);
- if (tmp < 0)
- return tmp;
- return put_user(tmp, p);
- case SOUND_MIXER_READ_RECSRC:
- tmp = snd_mixer_oss_get_recsrc(fmixer);
- if (tmp < 0)
- return tmp;
- return put_user(tmp, p);
- }
- }
- if (cmd & SIOC_IN) {
- if (get_user(tmp, p))
- return -EFAULT;
- tmp = snd_mixer_oss_set_volume(fmixer, cmd & 0xff, tmp);
- if (tmp < 0)
- return tmp;
- return put_user(tmp, p);
- } else if (cmd & SIOC_OUT) {
- tmp = snd_mixer_oss_get_volume(fmixer, cmd & 0xff);
- if (tmp < 0)
- return tmp;
- return put_user(tmp, p);
- }
- return -ENXIO;
-}
-
-static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- return snd_mixer_oss_ioctl1(file->private_data, cmd, arg);
-}
-
-int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg)
-{
- struct snd_mixer_oss_file fmixer;
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- if (card->mixer_oss == NULL)
- return -ENXIO;
- memset(&fmixer, 0, sizeof(fmixer));
- fmixer.card = card;
- fmixer.mixer = card->mixer_oss;
- return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
-}
-
-#ifdef CONFIG_COMPAT
-/* all compatible */
-#define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl
-#else
-#define snd_mixer_oss_ioctl_compat NULL
-#endif
-
-/*
- * REGISTRATION PART
- */
-
-static const struct file_operations snd_mixer_oss_f_ops =
-{
- .owner = THIS_MODULE,
- .open = snd_mixer_oss_open,
- .release = snd_mixer_oss_release,
- .llseek = no_llseek,
- .unlocked_ioctl = snd_mixer_oss_ioctl,
- .compat_ioctl = snd_mixer_oss_ioctl_compat,
-};
-
-/*
- * utilities
- */
-
-static long snd_mixer_oss_conv(long val, long omin, long omax, long nmin, long nmax)
-{
- long orange = omax - omin, nrange = nmax - nmin;
-
- if (orange == 0)
- return 0;
- return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin;
-}
-
-/* convert from alsa native to oss values (0-100) */
-static long snd_mixer_oss_conv1(long val, long min, long max, int *old)
-{
- if (val == snd_mixer_oss_conv(*old, 0, 100, min, max))
- return *old;
- return snd_mixer_oss_conv(val, min, max, 0, 100);
-}
-
-/* convert from oss to alsa native values */
-static long snd_mixer_oss_conv2(long val, long min, long max)
-{
- return snd_mixer_oss_conv(val, 0, 100, min, max);
-}
-
-#if 0
-static void snd_mixer_oss_recsrce_set(struct snd_card *card, int slot)
-{
- struct snd_mixer_oss *mixer = card->mixer_oss;
- if (mixer)
- mixer->mask_recsrc |= 1 << slot;
-}
-
-static int snd_mixer_oss_recsrce_get(struct snd_card *card, int slot)
-{
- struct snd_mixer_oss *mixer = card->mixer_oss;
- if (mixer && (mixer->mask_recsrc & (1 << slot)))
- return 1;
- return 0;
-}
-#endif
-
-#define SNDRV_MIXER_OSS_SIGNATURE 0x65999250
-
-#define SNDRV_MIXER_OSS_ITEM_GLOBAL 0
-#define SNDRV_MIXER_OSS_ITEM_GSWITCH 1
-#define SNDRV_MIXER_OSS_ITEM_GROUTE 2
-#define SNDRV_MIXER_OSS_ITEM_GVOLUME 3
-#define SNDRV_MIXER_OSS_ITEM_PSWITCH 4
-#define SNDRV_MIXER_OSS_ITEM_PROUTE 5
-#define SNDRV_MIXER_OSS_ITEM_PVOLUME 6
-#define SNDRV_MIXER_OSS_ITEM_CSWITCH 7
-#define SNDRV_MIXER_OSS_ITEM_CROUTE 8
-#define SNDRV_MIXER_OSS_ITEM_CVOLUME 9
-#define SNDRV_MIXER_OSS_ITEM_CAPTURE 10
-
-#define SNDRV_MIXER_OSS_ITEM_COUNT 11
-
-#define SNDRV_MIXER_OSS_PRESENT_GLOBAL (1<<0)
-#define SNDRV_MIXER_OSS_PRESENT_GSWITCH (1<<1)
-#define SNDRV_MIXER_OSS_PRESENT_GROUTE (1<<2)
-#define SNDRV_MIXER_OSS_PRESENT_GVOLUME (1<<3)
-#define SNDRV_MIXER_OSS_PRESENT_PSWITCH (1<<4)
-#define SNDRV_MIXER_OSS_PRESENT_PROUTE (1<<5)
-#define SNDRV_MIXER_OSS_PRESENT_PVOLUME (1<<6)
-#define SNDRV_MIXER_OSS_PRESENT_CSWITCH (1<<7)
-#define SNDRV_MIXER_OSS_PRESENT_CROUTE (1<<8)
-#define SNDRV_MIXER_OSS_PRESENT_CVOLUME (1<<9)
-#define SNDRV_MIXER_OSS_PRESENT_CAPTURE (1<<10)
-
-struct slot {
- unsigned int signature;
- unsigned int present;
- unsigned int channels;
- unsigned int numid[SNDRV_MIXER_OSS_ITEM_COUNT];
- unsigned int capture_item;
- struct snd_mixer_oss_assign_table *assigned;
- unsigned int allocated: 1;
-};
-
-#define ID_UNKNOWN ((unsigned int)-1)
-
-static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, const char *name, int index)
-{
- struct snd_card *card = mixer->card;
- struct snd_ctl_elem_id id;
-
- memset(&id, 0, sizeof(id));
- id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- strlcpy(id.name, name, sizeof(id.name));
- id.index = index;
- return snd_ctl_find_id(card, &id);
-}
-
-static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- unsigned int numid,
- int *left, int *right)
-{
- struct snd_ctl_elem_info *uinfo;
- struct snd_ctl_elem_value *uctl;
- struct snd_kcontrol *kctl;
- struct snd_card *card = fmixer->card;
-
- if (numid == ID_UNKNOWN)
- return;
- down_read(&card->controls_rwsem);
- if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
- up_read(&card->controls_rwsem);
- return;
- }
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
- if (uinfo == NULL || uctl == NULL)
- goto __unalloc;
- if (kctl->info(kctl, uinfo))
- goto __unalloc;
- if (kctl->get(kctl, uctl))
- goto __unalloc;
- if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN &&
- uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1)
- goto __unalloc;
- *left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]);
- if (uinfo->count > 1)
- *right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]);
- __unalloc:
- up_read(&card->controls_rwsem);
- kfree(uctl);
- kfree(uinfo);
-}
-
-static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- unsigned int numid,
- int *left, int *right,
- int route)
-{
- struct snd_ctl_elem_info *uinfo;
- struct snd_ctl_elem_value *uctl;
- struct snd_kcontrol *kctl;
- struct snd_card *card = fmixer->card;
-
- if (numid == ID_UNKNOWN)
- return;
- down_read(&card->controls_rwsem);
- if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
- up_read(&card->controls_rwsem);
- return;
- }
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
- if (uinfo == NULL || uctl == NULL)
- goto __unalloc;
- if (kctl->info(kctl, uinfo))
- goto __unalloc;
- if (kctl->get(kctl, uctl))
- goto __unalloc;
- if (!uctl->value.integer.value[0]) {
- *left = 0;
- if (uinfo->count == 1)
- *right = 0;
- }
- if (uinfo->count > 1 && !uctl->value.integer.value[route ? 3 : 1])
- *right = 0;
- __unalloc:
- up_read(&card->controls_rwsem);
- kfree(uctl);
- kfree(uinfo);
-}
-
-static int snd_mixer_oss_get_volume1(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- int *left, int *right)
-{
- struct slot *slot = pslot->private_data;
-
- *left = *right = 100;
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
- snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) {
- snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) {
- snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right);
- }
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) {
- snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) {
- snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) {
- snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) {
- snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
- }
- return 0;
-}
-
-static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- unsigned int numid,
- int left, int right)
-{
- struct snd_ctl_elem_info *uinfo;
- struct snd_ctl_elem_value *uctl;
- struct snd_kcontrol *kctl;
- struct snd_card *card = fmixer->card;
- int res;
-
- if (numid == ID_UNKNOWN)
- return;
- down_read(&card->controls_rwsem);
- if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
- up_read(&card->controls_rwsem);
- return;
- }
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
- if (uinfo == NULL || uctl == NULL)
- goto __unalloc;
- if (kctl->info(kctl, uinfo))
- goto __unalloc;
- if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN &&
- uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1)
- goto __unalloc;
- uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max);
- if (uinfo->count > 1)
- uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max);
- if ((res = kctl->put(kctl, uctl)) < 0)
- goto __unalloc;
- if (res > 0)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
- __unalloc:
- up_read(&card->controls_rwsem);
- kfree(uctl);
- kfree(uinfo);
-}
-
-static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- unsigned int numid,
- int left, int right,
- int route)
-{
- struct snd_ctl_elem_info *uinfo;
- struct snd_ctl_elem_value *uctl;
- struct snd_kcontrol *kctl;
- struct snd_card *card = fmixer->card;
- int res;
-
- if (numid == ID_UNKNOWN)
- return;
- down_read(&card->controls_rwsem);
- if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
- up_read(&card->controls_rwsem);
- return;
- }
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
- if (uinfo == NULL || uctl == NULL)
- goto __unalloc;
- if (kctl->info(kctl, uinfo))
- goto __unalloc;
- if (uinfo->count > 1) {
- uctl->value.integer.value[0] = left > 0 ? 1 : 0;
- uctl->value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0;
- if (route) {
- uctl->value.integer.value[1] =
- uctl->value.integer.value[2] = 0;
- }
- } else {
- uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0;
- }
- if ((res = kctl->put(kctl, uctl)) < 0)
- goto __unalloc;
- if (res > 0)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
- __unalloc:
- up_read(&card->controls_rwsem);
- kfree(uctl);
- kfree(uinfo);
-}
-
-static int snd_mixer_oss_put_volume1(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- int left, int right)
-{
- struct slot *slot = pslot->private_data;
-
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
- snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME)
- snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME) {
- snd_mixer_oss_put_volume1_vol(fmixer, pslot,
- slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) {
- snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) {
- snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right);
- }
- if (left || right) {
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_CSWITCH)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], left, right, 0);
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_CROUTE)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], left, right, 1);
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
- } else {
- if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CSWITCH) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], left, right, 0);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CROUTE) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], left, right, 1);
- } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
- }
- }
- return 0;
-}
-
-static int snd_mixer_oss_get_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- int *active)
-{
- struct slot *slot = pslot->private_data;
- int left, right;
-
- left = right = 1;
- snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], &left, &right, 0);
- *active = (left || right) ? 1 : 0;
- return 0;
-}
-
-static int snd_mixer_oss_get_recsrc1_route(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- int *active)
-{
- struct slot *slot = pslot->private_data;
- int left, right;
-
- left = right = 1;
- snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], &left, &right, 1);
- *active = (left || right) ? 1 : 0;
- return 0;
-}
-
-static int snd_mixer_oss_put_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- int active)
-{
- struct slot *slot = pslot->private_data;
-
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0);
- return 0;
-}
-
-static int snd_mixer_oss_put_recsrc1_route(struct snd_mixer_oss_file *fmixer,
- struct snd_mixer_oss_slot *pslot,
- int active)
-{
- struct slot *slot = pslot->private_data;
-
- snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1);
- return 0;
-}
-
-static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned int *active_index)
-{
- struct snd_card *card = fmixer->card;
- struct snd_mixer_oss *mixer = fmixer->mixer;
- struct snd_kcontrol *kctl;
- struct snd_mixer_oss_slot *pslot;
- struct slot *slot;
- struct snd_ctl_elem_info *uinfo;
- struct snd_ctl_elem_value *uctl;
- int err, idx;
-
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
- if (uinfo == NULL || uctl == NULL) {
- err = -ENOMEM;
- goto __free_only;
- }
- down_read(&card->controls_rwsem);
- kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
- if (! kctl) {
- err = -ENOENT;
- goto __unlock;
- }
- if ((err = kctl->info(kctl, uinfo)) < 0)
- goto __unlock;
- if ((err = kctl->get(kctl, uctl)) < 0)
- goto __unlock;
- for (idx = 0; idx < 32; idx++) {
- if (!(mixer->mask_recsrc & (1 << idx)))
- continue;
- pslot = &mixer->slots[idx];
- slot = pslot->private_data;
- if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE)
- continue;
- if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
- continue;
- if (slot->capture_item == uctl->value.enumerated.item[0]) {
- *active_index = idx;
- break;
- }
- }
- err = 0;
- __unlock:
- up_read(&card->controls_rwsem);
- __free_only:
- kfree(uctl);
- kfree(uinfo);
- return err;
-}
-
-static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned int active_index)
-{
- struct snd_card *card = fmixer->card;
- struct snd_mixer_oss *mixer = fmixer->mixer;
- struct snd_kcontrol *kctl;
- struct snd_mixer_oss_slot *pslot;
- struct slot *slot = NULL;
- struct snd_ctl_elem_info *uinfo;
- struct snd_ctl_elem_value *uctl;
- int err;
- unsigned int idx;
-
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
- if (uinfo == NULL || uctl == NULL) {
- err = -ENOMEM;
- goto __free_only;
- }
- down_read(&card->controls_rwsem);
- kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
- if (! kctl) {
- err = -ENOENT;
- goto __unlock;
- }
- if ((err = kctl->info(kctl, uinfo)) < 0)
- goto __unlock;
- for (idx = 0; idx < 32; idx++) {
- if (!(mixer->mask_recsrc & (1 << idx)))
- continue;
- pslot = &mixer->slots[idx];
- slot = pslot->private_data;
- if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE)
- continue;
- if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
- continue;
- if (idx == active_index)
- break;
- slot = NULL;
- }
- if (! slot)
- goto __unlock;
- for (idx = 0; idx < uinfo->count; idx++)
- uctl->value.enumerated.item[idx] = slot->capture_item;
- err = kctl->put(kctl, uctl);
- if (err > 0)
- snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
- err = 0;
- __unlock:
- up_read(&card->controls_rwsem);
- __free_only:
- kfree(uctl);
- kfree(uinfo);
- return err;
-}
-
-struct snd_mixer_oss_assign_table {
- int oss_id;
- const char *name;
- int index;
-};
-
-static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *slot, const char *name, int index, int item)
-{
- struct snd_ctl_elem_info *info;
- struct snd_kcontrol *kcontrol;
- struct snd_card *card = mixer->card;
- int err;
-
- down_read(&card->controls_rwsem);
- kcontrol = snd_mixer_oss_test_id(mixer, name, index);
- if (kcontrol == NULL) {
- up_read(&card->controls_rwsem);
- return 0;
- }
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info) {
- up_read(&card->controls_rwsem);
- return -ENOMEM;
- }
- if ((err = kcontrol->info(kcontrol, info)) < 0) {
- up_read(&card->controls_rwsem);
- kfree(info);
- return err;
- }
- slot->numid[item] = kcontrol->id.numid;
- up_read(&card->controls_rwsem);
- if (info->count > slot->channels)
- slot->channels = info->count;
- slot->present |= 1 << item;
- kfree(info);
- return 0;
-}
-
-static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn)
-{
- struct slot *p = chn->private_data;
- if (p) {
- if (p->allocated && p->assigned) {
- kfree(p->assigned->name);
- kfree(p->assigned);
- }
- kfree(p);
- }
-}
-
-static void mixer_slot_clear(struct snd_mixer_oss_slot *rslot)
-{
- int idx = rslot->number; /* remember this */
- if (rslot->private_free)
- rslot->private_free(rslot);
- memset(rslot, 0, sizeof(*rslot));
- rslot->number = idx;
-}
-
-/* In a separate function to keep gcc 3.2 happy - do NOT merge this in
- snd_mixer_oss_build_input! */
-static int snd_mixer_oss_build_test_all(struct snd_mixer_oss *mixer,
- struct snd_mixer_oss_assign_table *ptr,
- struct slot *slot)
-{
- char str[64];
- int err;
-
- err = snd_mixer_oss_build_test(mixer, slot, ptr->name, ptr->index,
- SNDRV_MIXER_OSS_ITEM_GLOBAL);
- if (err)
- return err;
- sprintf(str, "%s Switch", ptr->name);
- err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index,
- SNDRV_MIXER_OSS_ITEM_GSWITCH);
- if (err)
- return err;
- sprintf(str, "%s Route", ptr->name);
- err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index,
- SNDRV_MIXER_OSS_ITEM_GROUTE);
- if (err)
- return err;
- sprintf(str, "%s Volume", ptr->name);
- err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index,
- SNDRV_MIXER_OSS_ITEM_GVOLUME);
- if (err)
- return err;
- sprintf(str, "%s Playback Switch", ptr->name);
- err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index,
- SNDRV_MIXER_OSS_ITEM_PSWITCH);
- if (err)
- return err;
- sprintf(str, "%s Playback Route", ptr->name);
- err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index,
- SNDRV_MIXER_OSS_ITEM_PROUTE);
- if (err)
- return err;
- sprintf(str, "%s Playback Volume", ptr->name);
- err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index,
- SNDRV_MIXER_OSS_ITEM_PVOLUME);
- if (err)
- return err;
- sprintf(str, "%s Capture Switch", ptr->name);
- err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index,
- SNDRV_MIXER_OSS_ITEM_CSWITCH);
- if (err)
- return err;
- sprintf(str, "%s Capture Route", ptr->name);
- err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index,
- SNDRV_MIXER_OSS_ITEM_CROUTE);
- if (err)
- return err;
- sprintf(str, "%s Capture Volume", ptr->name);
- err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index,
- SNDRV_MIXER_OSS_ITEM_CVOLUME);
- if (err)
- return err;
-
- return 0;
-}
-
-/*
- * build an OSS mixer element.
- * ptr_allocated means the entry is dynamically allocated (change via proc file).
- * when replace_old = 1, the old entry is replaced with the new one.
- */
-static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mixer_oss_assign_table *ptr, int ptr_allocated, int replace_old)
-{
- struct slot slot;
- struct slot *pslot;
- struct snd_kcontrol *kctl;
- struct snd_mixer_oss_slot *rslot;
- char str[64];
-
- /* check if already assigned */
- if (mixer->slots[ptr->oss_id].get_volume && ! replace_old)
- return 0;
-
- memset(&slot, 0, sizeof(slot));
- memset(slot.numid, 0xff, sizeof(slot.numid)); /* ID_UNKNOWN */
- if (snd_mixer_oss_build_test_all(mixer, ptr, &slot))
- return 0;
- down_read(&mixer->card->controls_rwsem);
- if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) {
- struct snd_ctl_elem_info *uinfo;
-
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- if (! uinfo) {
- up_read(&mixer->card->controls_rwsem);
- return -ENOMEM;
- }
-
- if (kctl->info(kctl, uinfo)) {
- up_read(&mixer->card->controls_rwsem);
- return 0;
- }
- strcpy(str, ptr->name);
- if (!strcmp(str, "Master"))
- strcpy(str, "Mix");
- if (!strcmp(str, "Master Mono"))
- strcpy(str, "Mix Mono");
- slot.capture_item = 0;
- if (!strcmp(uinfo->value.enumerated.name, str)) {
- slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;
- } else {
- for (slot.capture_item = 1; slot.capture_item < uinfo->value.enumerated.items; slot.capture_item++) {
- uinfo->value.enumerated.item = slot.capture_item;
- if (kctl->info(kctl, uinfo)) {
- up_read(&mixer->card->controls_rwsem);
- return 0;
- }
- if (!strcmp(uinfo->value.enumerated.name, str)) {
- slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;
- break;
- }
- }
- }
- kfree(uinfo);
- }
- up_read(&mixer->card->controls_rwsem);
- if (slot.present != 0) {
- pslot = kmalloc(sizeof(slot), GFP_KERNEL);
- if (! pslot)
- return -ENOMEM;
- *pslot = slot;
- pslot->signature = SNDRV_MIXER_OSS_SIGNATURE;
- pslot->assigned = ptr;
- pslot->allocated = ptr_allocated;
- rslot = &mixer->slots[ptr->oss_id];
- mixer_slot_clear(rslot);
- rslot->stereo = slot.channels > 1 ? 1 : 0;
- rslot->get_volume = snd_mixer_oss_get_volume1;
- rslot->put_volume = snd_mixer_oss_put_volume1;
- /* note: ES18xx have both Capture Source and XX Capture Volume !!! */
- if (slot.present & SNDRV_MIXER_OSS_PRESENT_CSWITCH) {
- rslot->get_recsrc = snd_mixer_oss_get_recsrc1_sw;
- rslot->put_recsrc = snd_mixer_oss_put_recsrc1_sw;
- } else if (slot.present & SNDRV_MIXER_OSS_PRESENT_CROUTE) {
- rslot->get_recsrc = snd_mixer_oss_get_recsrc1_route;
- rslot->put_recsrc = snd_mixer_oss_put_recsrc1_route;
- } else if (slot.present & SNDRV_MIXER_OSS_PRESENT_CAPTURE) {
- mixer->mask_recsrc |= 1 << ptr->oss_id;
- }
- rslot->private_data = pslot;
- rslot->private_free = snd_mixer_oss_slot_free;
- return 1;
- }
- return 0;
-}
-
-#ifdef CONFIG_PROC_FS
-/*
- */
-#define MIXER_VOL(name) [SOUND_MIXER_##name] = #name
-static char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
- MIXER_VOL(VOLUME),
- MIXER_VOL(BASS),
- MIXER_VOL(TREBLE),
- MIXER_VOL(SYNTH),
- MIXER_VOL(PCM),
- MIXER_VOL(SPEAKER),
- MIXER_VOL(LINE),
- MIXER_VOL(MIC),
- MIXER_VOL(CD),
- MIXER_VOL(IMIX),
- MIXER_VOL(ALTPCM),
- MIXER_VOL(RECLEV),
- MIXER_VOL(IGAIN),
- MIXER_VOL(OGAIN),
- MIXER_VOL(LINE1),
- MIXER_VOL(LINE2),
- MIXER_VOL(LINE3),
- MIXER_VOL(DIGITAL1),
- MIXER_VOL(DIGITAL2),
- MIXER_VOL(DIGITAL3),
- MIXER_VOL(PHONEIN),
- MIXER_VOL(PHONEOUT),
- MIXER_VOL(VIDEO),
- MIXER_VOL(RADIO),
- MIXER_VOL(MONITOR),
-};
-
-/*
- * /proc interface
- */
-
-static void snd_mixer_oss_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_mixer_oss *mixer = entry->private_data;
- int i;
-
- mutex_lock(&mixer->reg_mutex);
- for (i = 0; i < SNDRV_OSS_MAX_MIXERS; i++) {
- struct slot *p;
-
- if (! oss_mixer_names[i])
- continue;
- p = (struct slot *)mixer->slots[i].private_data;
- snd_iprintf(buffer, "%s ", oss_mixer_names[i]);
- if (p && p->assigned)
- snd_iprintf(buffer, "\"%s\" %d\n",
- p->assigned->name,
- p->assigned->index);
- else
- snd_iprintf(buffer, "\"\" 0\n");
- }
- mutex_unlock(&mixer->reg_mutex);
-}
-
-static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_mixer_oss *mixer = entry->private_data;
- char line[128], str[32], idxstr[16];
- const char *cptr;
- int ch, idx;
- struct snd_mixer_oss_assign_table *tbl;
- struct slot *slot;
-
- while (!snd_info_get_line(buffer, line, sizeof(line))) {
- cptr = snd_info_get_str(str, line, sizeof(str));
- for (ch = 0; ch < SNDRV_OSS_MAX_MIXERS; ch++)
- if (oss_mixer_names[ch] && strcmp(oss_mixer_names[ch], str) == 0)
- break;
- if (ch >= SNDRV_OSS_MAX_MIXERS) {
- snd_printk(KERN_ERR "mixer_oss: invalid OSS volume '%s'\n", str);
- continue;
- }
- cptr = snd_info_get_str(str, cptr, sizeof(str));
- if (! *str) {
- /* remove the entry */
- mutex_lock(&mixer->reg_mutex);
- mixer_slot_clear(&mixer->slots[ch]);
- mutex_unlock(&mixer->reg_mutex);
- continue;
- }
- snd_info_get_str(idxstr, cptr, sizeof(idxstr));
- idx = simple_strtoul(idxstr, NULL, 10);
- if (idx >= 0x4000) { /* too big */
- snd_printk(KERN_ERR "mixer_oss: invalid index %d\n", idx);
- continue;
- }
- mutex_lock(&mixer->reg_mutex);
- slot = (struct slot *)mixer->slots[ch].private_data;
- if (slot && slot->assigned &&
- slot->assigned->index == idx && ! strcmp(slot->assigned->name, str))
- /* not changed */
- goto __unlock;
- tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
- if (! tbl) {
- snd_printk(KERN_ERR "mixer_oss: no memory\n");
- goto __unlock;
- }
- tbl->oss_id = ch;
- tbl->name = kstrdup(str, GFP_KERNEL);
- if (! tbl->name) {
- kfree(tbl);
- goto __unlock;
- }
- tbl->index = idx;
- if (snd_mixer_oss_build_input(mixer, tbl, 1, 1) <= 0) {
- kfree(tbl->name);
- kfree(tbl);
- }
- __unlock:
- mutex_unlock(&mixer->reg_mutex);
- }
-}
-
-static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer)
-{
- struct snd_info_entry *entry;
-
- entry = snd_info_create_card_entry(mixer->card, "oss_mixer",
- mixer->card->proc_root);
- if (! entry)
- return;
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
- entry->c.text.read = snd_mixer_oss_proc_read;
- entry->c.text.write = snd_mixer_oss_proc_write;
- entry->private_data = mixer;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- mixer->proc_entry = entry;
-}
-
-static void snd_mixer_oss_proc_done(struct snd_mixer_oss *mixer)
-{
- snd_info_free_entry(mixer->proc_entry);
- mixer->proc_entry = NULL;
-}
-#else /* !CONFIG_PROC_FS */
-#define snd_mixer_oss_proc_init(mix)
-#define snd_mixer_oss_proc_done(mix)
-#endif /* CONFIG_PROC_FS */
-
-static void snd_mixer_oss_build(struct snd_mixer_oss *mixer)
-{
- static struct snd_mixer_oss_assign_table table[] = {
- { SOUND_MIXER_VOLUME, "Master", 0 },
- { SOUND_MIXER_VOLUME, "Front", 0 }, /* fallback */
- { SOUND_MIXER_BASS, "Tone Control - Bass", 0 },
- { SOUND_MIXER_TREBLE, "Tone Control - Treble", 0 },
- { SOUND_MIXER_SYNTH, "Synth", 0 },
- { SOUND_MIXER_SYNTH, "FM", 0 }, /* fallback */
- { SOUND_MIXER_SYNTH, "Music", 0 }, /* fallback */
- { SOUND_MIXER_PCM, "PCM", 0 },
- { SOUND_MIXER_SPEAKER, "Beep", 0 },
- { SOUND_MIXER_SPEAKER, "PC Speaker", 0 }, /* fallback */
- { SOUND_MIXER_SPEAKER, "Speaker", 0 }, /* fallback */
- { SOUND_MIXER_LINE, "Line", 0 },
- { SOUND_MIXER_MIC, "Mic", 0 },
- { SOUND_MIXER_CD, "CD", 0 },
- { SOUND_MIXER_IMIX, "Monitor Mix", 0 },
- { SOUND_MIXER_ALTPCM, "PCM", 1 },
- { SOUND_MIXER_ALTPCM, "Headphone", 0 }, /* fallback */
- { SOUND_MIXER_ALTPCM, "Wave", 0 }, /* fallback */
- { SOUND_MIXER_RECLEV, "-- nothing --", 0 },
- { SOUND_MIXER_IGAIN, "Capture", 0 },
- { SOUND_MIXER_OGAIN, "Playback", 0 },
- { SOUND_MIXER_LINE1, "Aux", 0 },
- { SOUND_MIXER_LINE2, "Aux", 1 },
- { SOUND_MIXER_LINE3, "Aux", 2 },
- { SOUND_MIXER_DIGITAL1, "Digital", 0 },
- { SOUND_MIXER_DIGITAL1, "IEC958", 0 }, /* fallback */
- { SOUND_MIXER_DIGITAL1, "IEC958 Optical", 0 }, /* fallback */
- { SOUND_MIXER_DIGITAL1, "IEC958 Coaxial", 0 }, /* fallback */
- { SOUND_MIXER_DIGITAL2, "Digital", 1 },
- { SOUND_MIXER_DIGITAL3, "Digital", 2 },
- { SOUND_MIXER_PHONEIN, "Phone", 0 },
- { SOUND_MIXER_PHONEOUT, "Master Mono", 0 },
- { SOUND_MIXER_PHONEOUT, "Speaker", 0 }, /*fallback*/
- { SOUND_MIXER_PHONEOUT, "Mono", 0 }, /*fallback*/
- { SOUND_MIXER_PHONEOUT, "Phone", 0 }, /* fallback */
- { SOUND_MIXER_VIDEO, "Video", 0 },
- { SOUND_MIXER_RADIO, "Radio", 0 },
- { SOUND_MIXER_MONITOR, "Monitor", 0 }
- };
- unsigned int idx;
-
- for (idx = 0; idx < ARRAY_SIZE(table); idx++)
- snd_mixer_oss_build_input(mixer, &table[idx], 0, 0);
- if (mixer->mask_recsrc) {
- mixer->get_recsrc = snd_mixer_oss_get_recsrc2;
- mixer->put_recsrc = snd_mixer_oss_put_recsrc2;
- }
-}
-
-/*
- *
- */
-
-static int snd_mixer_oss_free1(void *private)
-{
- struct snd_mixer_oss *mixer = private;
- struct snd_card *card;
- int idx;
-
- if (!mixer)
- return 0;
- card = mixer->card;
- if (snd_BUG_ON(mixer != card->mixer_oss))
- return -ENXIO;
- card->mixer_oss = NULL;
- for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++) {
- struct snd_mixer_oss_slot *chn = &mixer->slots[idx];
- if (chn->private_free)
- chn->private_free(chn);
- }
- kfree(mixer);
- return 0;
-}
-
-static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
-{
- struct snd_mixer_oss *mixer;
-
- if (cmd == SND_MIXER_OSS_NOTIFY_REGISTER) {
- char name[128];
- int idx, err;
-
- mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL);
- if (mixer == NULL)
- return -ENOMEM;
- mutex_init(&mixer->reg_mutex);
- sprintf(name, "mixer%i%i", card->number, 0);
- if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
- card, 0,
- &snd_mixer_oss_f_ops, card,
- name)) < 0) {
- snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n",
- card->number, 0);
- kfree(mixer);
- return err;
- }
- mixer->oss_dev_alloc = 1;
- mixer->card = card;
- if (*card->mixername)
- strlcpy(mixer->name, card->mixername, sizeof(mixer->name));
- else
- strlcpy(mixer->name, name, sizeof(mixer->name));
-#ifdef SNDRV_OSS_INFO_DEV_MIXERS
- snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIXERS,
- card->number,
- mixer->name);
-#endif
- for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++)
- mixer->slots[idx].number = idx;
- card->mixer_oss = mixer;
- snd_mixer_oss_build(mixer);
- snd_mixer_oss_proc_init(mixer);
- } else {
- mixer = card->mixer_oss;
- if (mixer == NULL)
- return 0;
- if (mixer->oss_dev_alloc) {
-#ifdef SNDRV_OSS_INFO_DEV_MIXERS
- snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number);
-#endif
- snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0);
- mixer->oss_dev_alloc = 0;
- }
- if (cmd == SND_MIXER_OSS_NOTIFY_DISCONNECT)
- return 0;
- snd_mixer_oss_proc_done(mixer);
- return snd_mixer_oss_free1(mixer);
- }
- return 0;
-}
-
-static int __init alsa_mixer_oss_init(void)
-{
- int idx;
-
- snd_mixer_oss_notify_callback = snd_mixer_oss_notify_handler;
- for (idx = 0; idx < SNDRV_CARDS; idx++) {
- if (snd_cards[idx])
- snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_REGISTER);
- }
- return 0;
-}
-
-static void __exit alsa_mixer_oss_exit(void)
-{
- int idx;
-
- snd_mixer_oss_notify_callback = NULL;
- for (idx = 0; idx < SNDRV_CARDS; idx++) {
- if (snd_cards[idx])
- snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_FREE);
- }
-}
-
-module_init(alsa_mixer_oss_init)
-module_exit(alsa_mixer_oss_exit)
-
-EXPORT_SYMBOL(snd_mixer_oss_ioctl_card);
diff --git a/ANDROID_3.4.5/sound/core/oss/mulaw.c b/ANDROID_3.4.5/sound/core/oss/mulaw.c
deleted file mode 100644
index 7915564b..00000000
--- a/ANDROID_3.4.5/sound/core/oss/mulaw.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Mu-Law conversion Plug-In Interface
- * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
- * Uros Bizjak <uros@kss-loka.si>
- *
- * Based on reference implementation by Sun Microsystems, Inc.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/time.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include "pcm_plugin.h"
-
-#define SIGN_BIT (0x80) /* Sign bit for a u-law byte. */
-#define QUANT_MASK (0xf) /* Quantization field mask. */
-#define NSEGS (8) /* Number of u-law segments. */
-#define SEG_SHIFT (4) /* Left shift for segment number. */
-#define SEG_MASK (0x70) /* Segment field mask. */
-
-static inline int val_seg(int val)
-{
- int r = 0;
- val >>= 7;
- if (val & 0xf0) {
- val >>= 4;
- r += 4;
- }
- if (val & 0x0c) {
- val >>= 2;
- r += 2;
- }
- if (val & 0x02)
- r += 1;
- return r;
-}
-
-#define BIAS (0x84) /* Bias for linear code. */
-
-/*
- * linear2ulaw() - Convert a linear PCM value to u-law
- *
- * In order to simplify the encoding process, the original linear magnitude
- * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
- * (33 - 8191). The result can be seen in the following encoding table:
- *
- * Biased Linear Input Code Compressed Code
- * ------------------------ ---------------
- * 00000001wxyza 000wxyz
- * 0000001wxyzab 001wxyz
- * 000001wxyzabc 010wxyz
- * 00001wxyzabcd 011wxyz
- * 0001wxyzabcde 100wxyz
- * 001wxyzabcdef 101wxyz
- * 01wxyzabcdefg 110wxyz
- * 1wxyzabcdefgh 111wxyz
- *
- * Each biased linear code has a leading 1 which identifies the segment
- * number. The value of the segment number is equal to 7 minus the number
- * of leading 0's. The quantization interval is directly available as the
- * four bits wxyz. * The trailing bits (a - h) are ignored.
- *
- * Ordinarily the complement of the resulting code word is used for
- * transmission, and so the code word is complemented before it is returned.
- *
- * For further information see John C. Bellamy's Digital Telephony, 1982,
- * John Wiley & Sons, pps 98-111 and 472-476.
- */
-static unsigned char linear2ulaw(int pcm_val) /* 2's complement (16-bit range) */
-{
- int mask;
- int seg;
- unsigned char uval;
-
- /* Get the sign and the magnitude of the value. */
- if (pcm_val < 0) {
- pcm_val = BIAS - pcm_val;
- mask = 0x7F;
- } else {
- pcm_val += BIAS;
- mask = 0xFF;
- }
- if (pcm_val > 0x7FFF)
- pcm_val = 0x7FFF;
-
- /* Convert the scaled magnitude to segment number. */
- seg = val_seg(pcm_val);
-
- /*
- * Combine the sign, segment, quantization bits;
- * and complement the code word.
- */
- uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
- return uval ^ mask;
-}
-
-/*
- * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
- *
- * First, a biased linear code is derived from the code word. An unbiased
- * output can then be obtained by subtracting 33 from the biased code.
- *
- * Note that this function expects to be passed the complement of the
- * original code word. This is in keeping with ISDN conventions.
- */
-static int ulaw2linear(unsigned char u_val)
-{
- int t;
-
- /* Complement to obtain normal u-law value. */
- u_val = ~u_val;
-
- /*
- * Extract and bias the quantization bits. Then
- * shift up by the segment number and subtract out the bias.
- */
- t = ((u_val & QUANT_MASK) << 3) + BIAS;
- t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
-
- return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
-}
-
-/*
- * Basic Mu-Law plugin
- */
-
-typedef void (*mulaw_f)(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames);
-
-struct mulaw_priv {
- mulaw_f func;
- int cvt_endian; /* need endian conversion? */
- unsigned int native_ofs; /* byte offset in native format */
- unsigned int copy_ofs; /* byte offset in s16 format */
- unsigned int native_bytes; /* byte size of the native format */
- unsigned int copy_bytes; /* bytes to copy per conversion */
- u16 flip; /* MSB flip for signedness, done after endian conversion */
-};
-
-static inline void cvt_s16_to_native(struct mulaw_priv *data,
- unsigned char *dst, u16 sample)
-{
- sample ^= data->flip;
- if (data->cvt_endian)
- sample = swab16(sample);
- if (data->native_bytes > data->copy_bytes)
- memset(dst, 0, data->native_bytes);
- memcpy(dst + data->native_ofs, (char *)&sample + data->copy_ofs,
- data->copy_bytes);
-}
-
-static void mulaw_decode(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data;
- int channel;
- int nchannels = plugin->src_format.channels;
- for (channel = 0; channel < nchannels; ++channel) {
- char *src;
- char *dst;
- int src_step, dst_step;
- snd_pcm_uframes_t frames1;
- if (!src_channels[channel].enabled) {
- if (dst_channels[channel].wanted)
- snd_pcm_area_silence(&dst_channels[channel].area, 0, frames, plugin->dst_format.format);
- dst_channels[channel].enabled = 0;
- continue;
- }
- dst_channels[channel].enabled = 1;
- src = src_channels[channel].area.addr + src_channels[channel].area.first / 8;
- dst = dst_channels[channel].area.addr + dst_channels[channel].area.first / 8;
- src_step = src_channels[channel].area.step / 8;
- dst_step = dst_channels[channel].area.step / 8;
- frames1 = frames;
- while (frames1-- > 0) {
- signed short sample = ulaw2linear(*src);
- cvt_s16_to_native(data, dst, sample);
- src += src_step;
- dst += dst_step;
- }
- }
-}
-
-static inline signed short cvt_native_to_s16(struct mulaw_priv *data,
- unsigned char *src)
-{
- u16 sample = 0;
- memcpy((char *)&sample + data->copy_ofs, src + data->native_ofs,
- data->copy_bytes);
- if (data->cvt_endian)
- sample = swab16(sample);
- sample ^= data->flip;
- return (signed short)sample;
-}
-
-static void mulaw_encode(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data;
- int channel;
- int nchannels = plugin->src_format.channels;
- for (channel = 0; channel < nchannels; ++channel) {
- char *src;
- char *dst;
- int src_step, dst_step;
- snd_pcm_uframes_t frames1;
- if (!src_channels[channel].enabled) {
- if (dst_channels[channel].wanted)
- snd_pcm_area_silence(&dst_channels[channel].area, 0, frames, plugin->dst_format.format);
- dst_channels[channel].enabled = 0;
- continue;
- }
- dst_channels[channel].enabled = 1;
- src = src_channels[channel].area.addr + src_channels[channel].area.first / 8;
- dst = dst_channels[channel].area.addr + dst_channels[channel].area.first / 8;
- src_step = src_channels[channel].area.step / 8;
- dst_step = dst_channels[channel].area.step / 8;
- frames1 = frames;
- while (frames1-- > 0) {
- signed short sample = cvt_native_to_s16(data, src);
- *dst = linear2ulaw(sample);
- src += src_step;
- dst += dst_step;
- }
- }
-}
-
-static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- struct mulaw_priv *data;
-
- if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
- return -ENXIO;
- if (frames == 0)
- return 0;
-#ifdef CONFIG_SND_DEBUG
- {
- unsigned int channel;
- for (channel = 0; channel < plugin->src_format.channels; channel++) {
- if (snd_BUG_ON(src_channels[channel].area.first % 8 ||
- src_channels[channel].area.step % 8))
- return -ENXIO;
- if (snd_BUG_ON(dst_channels[channel].area.first % 8 ||
- dst_channels[channel].area.step % 8))
- return -ENXIO;
- }
- }
-#endif
- data = (struct mulaw_priv *)plugin->extra_data;
- data->func(plugin, src_channels, dst_channels, frames);
- return frames;
-}
-
-static void init_data(struct mulaw_priv *data, snd_pcm_format_t format)
-{
-#ifdef SNDRV_LITTLE_ENDIAN
- data->cvt_endian = snd_pcm_format_big_endian(format) > 0;
-#else
- data->cvt_endian = snd_pcm_format_little_endian(format) > 0;
-#endif
- if (!snd_pcm_format_signed(format))
- data->flip = 0x8000;
- data->native_bytes = snd_pcm_format_physical_width(format) / 8;
- data->copy_bytes = data->native_bytes < 2 ? 1 : 2;
- if (snd_pcm_format_little_endian(format)) {
- data->native_ofs = data->native_bytes - data->copy_bytes;
- data->copy_ofs = 2 - data->copy_bytes;
- } else {
- /* S24 in 4bytes need an 1 byte offset */
- data->native_ofs = data->native_bytes -
- snd_pcm_format_width(format) / 8;
- }
-}
-
-int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin)
-{
- int err;
- struct mulaw_priv *data;
- struct snd_pcm_plugin *plugin;
- struct snd_pcm_plugin_format *format;
- mulaw_f func;
-
- if (snd_BUG_ON(!r_plugin))
- return -ENXIO;
- *r_plugin = NULL;
-
- if (snd_BUG_ON(src_format->rate != dst_format->rate))
- return -ENXIO;
- if (snd_BUG_ON(src_format->channels != dst_format->channels))
- return -ENXIO;
-
- if (dst_format->format == SNDRV_PCM_FORMAT_MU_LAW) {
- format = src_format;
- func = mulaw_encode;
- }
- else if (src_format->format == SNDRV_PCM_FORMAT_MU_LAW) {
- format = dst_format;
- func = mulaw_decode;
- }
- else {
- snd_BUG();
- return -EINVAL;
- }
- if (snd_BUG_ON(!snd_pcm_format_linear(format->format)))
- return -ENXIO;
-
- err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion",
- src_format, dst_format,
- sizeof(struct mulaw_priv), &plugin);
- if (err < 0)
- return err;
- data = (struct mulaw_priv *)plugin->extra_data;
- data->func = func;
- init_data(data, format->format);
- plugin->transfer = mulaw_transfer;
- *r_plugin = plugin;
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/oss/pcm_oss.c b/ANDROID_3.4.5/sound/core/oss/pcm_oss.c
deleted file mode 100644
index 4c1cc517..00000000
--- a/ANDROID_3.4.5/sound/core/oss/pcm_oss.c
+++ /dev/null
@@ -1,3117 +0,0 @@
-/*
- * Digital Audio (PCM) abstract layer / OSS compatible
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#if 0
-#define PLUGIN_DEBUG
-#endif
-#if 0
-#define OSS_DEBUG
-#endif
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/math64.h>
-#include <linux/string.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include "pcm_plugin.h"
-#include <sound/info.h>
-#include <linux/soundcard.h>
-#include <sound/initval.h>
-#include <sound/mixer_oss.h>
-
-#define OSS_ALSAEMULVER _SIOR ('M', 249, int)
-
-static int dsp_map[SNDRV_CARDS];
-static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
-static bool nonblock_open = 1;
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
-MODULE_DESCRIPTION("PCM OSS emulation for ALSA.");
-MODULE_LICENSE("GPL");
-module_param_array(dsp_map, int, NULL, 0444);
-MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device.");
-module_param_array(adsp_map, int, NULL, 0444);
-MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device.");
-module_param(nonblock_open, bool, 0644);
-MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices.");
-MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM);
-MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1);
-
-static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
-static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
-static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
-
-static inline mm_segment_t snd_enter_user(void)
-{
- mm_segment_t fs = get_fs();
- set_fs(get_ds());
- return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
- set_fs(fs);
-}
-
-/*
- * helper functions to process hw_params
- */
-static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin)
-{
- int changed = 0;
- if (i->min < min) {
- i->min = min;
- i->openmin = openmin;
- changed = 1;
- } else if (i->min == min && !i->openmin && openmin) {
- i->openmin = 1;
- changed = 1;
- }
- if (i->integer) {
- if (i->openmin) {
- i->min++;
- i->openmin = 0;
- }
- }
- if (snd_interval_checkempty(i)) {
- snd_interval_none(i);
- return -EINVAL;
- }
- return changed;
-}
-
-static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax)
-{
- int changed = 0;
- if (i->max > max) {
- i->max = max;
- i->openmax = openmax;
- changed = 1;
- } else if (i->max == max && !i->openmax && openmax) {
- i->openmax = 1;
- changed = 1;
- }
- if (i->integer) {
- if (i->openmax) {
- i->max--;
- i->openmax = 0;
- }
- }
- if (snd_interval_checkempty(i)) {
- snd_interval_none(i);
- return -EINVAL;
- }
- return changed;
-}
-
-static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
-{
- struct snd_interval t;
- t.empty = 0;
- t.min = t.max = val;
- t.openmin = t.openmax = 0;
- t.integer = 1;
- return snd_interval_refine(i, &t);
-}
-
-/**
- * snd_pcm_hw_param_value_min
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Return the minimum value for field PAR.
- */
-static unsigned int
-snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, int *dir)
-{
- if (hw_is_mask(var)) {
- if (dir)
- *dir = 0;
- return snd_mask_min(hw_param_mask_c(params, var));
- }
- if (hw_is_interval(var)) {
- const struct snd_interval *i = hw_param_interval_c(params, var);
- if (dir)
- *dir = i->openmin;
- return snd_interval_min(i);
- }
- return -EINVAL;
-}
-
-/**
- * snd_pcm_hw_param_value_max
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Return the maximum value for field PAR.
- */
-static unsigned int
-snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, int *dir)
-{
- if (hw_is_mask(var)) {
- if (dir)
- *dir = 0;
- return snd_mask_max(hw_param_mask_c(params, var));
- }
- if (hw_is_interval(var)) {
- const struct snd_interval *i = hw_param_interval_c(params, var);
- if (dir)
- *dir = - (int) i->openmax;
- return snd_interval_max(i);
- }
- return -EINVAL;
-}
-
-static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var,
- const struct snd_mask *val)
-{
- int changed;
- changed = snd_mask_refine(hw_param_mask(params, var), val);
- if (changed) {
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- }
- return changed;
-}
-
-static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm,
- struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var,
- const struct snd_mask *val)
-{
- int changed = _snd_pcm_hw_param_mask(params, var, val);
- if (changed < 0)
- return changed;
- if (params->rmask) {
- int err = snd_pcm_hw_refine(pcm, params);
- if (err < 0)
- return err;
- }
- return 0;
-}
-
-static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, unsigned int val,
- int dir)
-{
- int changed;
- int open = 0;
- if (dir) {
- if (dir > 0) {
- open = 1;
- } else if (dir < 0) {
- if (val > 0) {
- open = 1;
- val--;
- }
- }
- }
- if (hw_is_mask(var))
- changed = snd_mask_refine_min(hw_param_mask(params, var),
- val + !!open);
- else if (hw_is_interval(var))
- changed = snd_interval_refine_min(hw_param_interval(params, var),
- val, open);
- else
- return -EINVAL;
- if (changed) {
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- }
- return changed;
-}
-
-/**
- * snd_pcm_hw_param_min
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @val: minimal value
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Inside configuration space defined by PARAMS remove from PAR all
- * values < VAL. Reduce configuration space accordingly.
- * Return new minimum or -EINVAL if the configuration space is empty
- */
-static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm,
- struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, unsigned int val,
- int *dir)
-{
- int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
- if (changed < 0)
- return changed;
- if (params->rmask) {
- int err = snd_pcm_hw_refine(pcm, params);
- if (err < 0)
- return err;
- }
- return snd_pcm_hw_param_value_min(params, var, dir);
-}
-
-static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, unsigned int val,
- int dir)
-{
- int changed;
- int open = 0;
- if (dir) {
- if (dir < 0) {
- open = 1;
- } else if (dir > 0) {
- open = 1;
- val++;
- }
- }
- if (hw_is_mask(var)) {
- if (val == 0 && open) {
- snd_mask_none(hw_param_mask(params, var));
- changed = -EINVAL;
- } else
- changed = snd_mask_refine_max(hw_param_mask(params, var),
- val - !!open);
- } else if (hw_is_interval(var))
- changed = snd_interval_refine_max(hw_param_interval(params, var),
- val, open);
- else
- return -EINVAL;
- if (changed) {
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- }
- return changed;
-}
-
-/**
- * snd_pcm_hw_param_max
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @val: maximal value
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Inside configuration space defined by PARAMS remove from PAR all
- * values >= VAL + 1. Reduce configuration space accordingly.
- * Return new maximum or -EINVAL if the configuration space is empty
- */
-static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm,
- struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, unsigned int val,
- int *dir)
-{
- int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
- if (changed < 0)
- return changed;
- if (params->rmask) {
- int err = snd_pcm_hw_refine(pcm, params);
- if (err < 0)
- return err;
- }
- return snd_pcm_hw_param_value_max(params, var, dir);
-}
-
-static int boundary_sub(int a, int adir,
- int b, int bdir,
- int *c, int *cdir)
-{
- adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
- bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
- *c = a - b;
- *cdir = adir - bdir;
- if (*cdir == -2) {
- (*c)--;
- } else if (*cdir == 2) {
- (*c)++;
- }
- return 0;
-}
-
-static int boundary_lt(unsigned int a, int adir,
- unsigned int b, int bdir)
-{
- if (adir < 0) {
- a--;
- adir = 1;
- } else if (adir > 0)
- adir = 1;
- if (bdir < 0) {
- b--;
- bdir = 1;
- } else if (bdir > 0)
- bdir = 1;
- return a < b || (a == b && adir < bdir);
-}
-
-/* Return 1 if min is nearer to best than max */
-static int boundary_nearer(int min, int mindir,
- int best, int bestdir,
- int max, int maxdir)
-{
- int dmin, dmindir;
- int dmax, dmaxdir;
- boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
- boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
- return boundary_lt(dmin, dmindir, dmax, dmaxdir);
-}
-
-/**
- * snd_pcm_hw_param_near
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @best: value to set
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Inside configuration space defined by PARAMS set PAR to the available value
- * nearest to VAL. Reduce configuration space accordingly.
- * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS,
- * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
- * Return the value found.
- */
-static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
- struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, unsigned int best,
- int *dir)
-{
- struct snd_pcm_hw_params *save = NULL;
- int v;
- unsigned int saved_min;
- int last = 0;
- int min, max;
- int mindir, maxdir;
- int valdir = dir ? *dir : 0;
- /* FIXME */
- if (best > INT_MAX)
- best = INT_MAX;
- min = max = best;
- mindir = maxdir = valdir;
- if (maxdir > 0)
- maxdir = 0;
- else if (maxdir == 0)
- maxdir = -1;
- else {
- maxdir = 1;
- max--;
- }
- save = kmalloc(sizeof(*save), GFP_KERNEL);
- if (save == NULL)
- return -ENOMEM;
- *save = *params;
- saved_min = min;
- min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
- if (min >= 0) {
- struct snd_pcm_hw_params *params1;
- if (max < 0)
- goto _end;
- if ((unsigned int)min == saved_min && mindir == valdir)
- goto _end;
- params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
- if (params1 == NULL) {
- kfree(save);
- return -ENOMEM;
- }
- *params1 = *save;
- max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
- if (max < 0) {
- kfree(params1);
- goto _end;
- }
- if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
- *params = *params1;
- last = 1;
- }
- kfree(params1);
- } else {
- *params = *save;
- max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
- if (max < 0) {
- kfree(save);
- return max;
- }
- last = 1;
- }
- _end:
- kfree(save);
- if (last)
- v = snd_pcm_hw_param_last(pcm, params, var, dir);
- else
- v = snd_pcm_hw_param_first(pcm, params, var, dir);
- snd_BUG_ON(v < 0);
- return v;
-}
-
-static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, unsigned int val,
- int dir)
-{
- int changed;
- if (hw_is_mask(var)) {
- struct snd_mask *m = hw_param_mask(params, var);
- if (val == 0 && dir < 0) {
- changed = -EINVAL;
- snd_mask_none(m);
- } else {
- if (dir > 0)
- val++;
- else if (dir < 0)
- val--;
- changed = snd_mask_refine_set(hw_param_mask(params, var), val);
- }
- } else if (hw_is_interval(var)) {
- struct snd_interval *i = hw_param_interval(params, var);
- if (val == 0 && dir < 0) {
- changed = -EINVAL;
- snd_interval_none(i);
- } else if (dir == 0)
- changed = snd_interval_refine_set(i, val);
- else {
- struct snd_interval t;
- t.openmin = 1;
- t.openmax = 1;
- t.empty = 0;
- t.integer = 0;
- if (dir < 0) {
- t.min = val - 1;
- t.max = val;
- } else {
- t.min = val;
- t.max = val+1;
- }
- changed = snd_interval_refine(i, &t);
- }
- } else
- return -EINVAL;
- if (changed) {
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- }
- return changed;
-}
-
-/**
- * snd_pcm_hw_param_set
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @val: value to set
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Inside configuration space defined by PARAMS remove from PAR all
- * values != VAL. Reduce configuration space accordingly.
- * Return VAL or -EINVAL if the configuration space is empty
- */
-static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm,
- struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, unsigned int val,
- int dir)
-{
- int changed = _snd_pcm_hw_param_set(params, var, val, dir);
- if (changed < 0)
- return changed;
- if (params->rmask) {
- int err = snd_pcm_hw_refine(pcm, params);
- if (err < 0)
- return err;
- }
- return snd_pcm_hw_param_value(params, var, NULL);
-}
-
-static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var)
-{
- int changed;
- changed = snd_interval_setinteger(hw_param_interval(params, var));
- if (changed) {
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- }
- return changed;
-}
-
-/*
- * plugin
- */
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_pcm_plugin *plugin, *next;
-
- plugin = runtime->oss.plugin_first;
- while (plugin) {
- next = plugin->next;
- snd_pcm_plugin_free(plugin);
- plugin = next;
- }
- runtime->oss.plugin_first = runtime->oss.plugin_last = NULL;
- return 0;
-}
-
-static int snd_pcm_plugin_insert(struct snd_pcm_plugin *plugin)
-{
- struct snd_pcm_runtime *runtime = plugin->plug->runtime;
- plugin->next = runtime->oss.plugin_first;
- plugin->prev = NULL;
- if (runtime->oss.plugin_first) {
- runtime->oss.plugin_first->prev = plugin;
- runtime->oss.plugin_first = plugin;
- } else {
- runtime->oss.plugin_last =
- runtime->oss.plugin_first = plugin;
- }
- return 0;
-}
-
-int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin)
-{
- struct snd_pcm_runtime *runtime = plugin->plug->runtime;
- plugin->next = NULL;
- plugin->prev = runtime->oss.plugin_last;
- if (runtime->oss.plugin_last) {
- runtime->oss.plugin_last->next = plugin;
- runtime->oss.plugin_last = plugin;
- } else {
- runtime->oss.plugin_last =
- runtime->oss.plugin_first = plugin;
- }
- return 0;
-}
-#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
-
-static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- long buffer_size = snd_pcm_lib_buffer_bytes(substream);
- long bytes = frames_to_bytes(runtime, frames);
- if (buffer_size == runtime->oss.buffer_bytes)
- return bytes;
-#if BITS_PER_LONG >= 64
- return runtime->oss.buffer_bytes * bytes / buffer_size;
-#else
- {
- u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes;
- return div_u64(bsize, buffer_size);
- }
-#endif
-}
-
-static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- long buffer_size = snd_pcm_lib_buffer_bytes(substream);
- if (buffer_size == runtime->oss.buffer_bytes)
- return bytes_to_frames(runtime, bytes);
- return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
-}
-
-static inline
-snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime)
-{
- return runtime->hw_ptr_interrupt;
-}
-
-/* define extended formats in the recent OSS versions (if any) */
-/* linear formats */
-#define AFMT_S32_LE 0x00001000
-#define AFMT_S32_BE 0x00002000
-#define AFMT_S24_LE 0x00008000
-#define AFMT_S24_BE 0x00010000
-#define AFMT_S24_PACKED 0x00040000
-
-/* other supported formats */
-#define AFMT_FLOAT 0x00004000
-#define AFMT_SPDIF_RAW 0x00020000
-
-/* unsupported formats */
-#define AFMT_AC3 0x00000400
-#define AFMT_VORBIS 0x00000800
-
-static snd_pcm_format_t snd_pcm_oss_format_from(int format)
-{
- switch (format) {
- case AFMT_MU_LAW: return SNDRV_PCM_FORMAT_MU_LAW;
- case AFMT_A_LAW: return SNDRV_PCM_FORMAT_A_LAW;
- case AFMT_IMA_ADPCM: return SNDRV_PCM_FORMAT_IMA_ADPCM;
- case AFMT_U8: return SNDRV_PCM_FORMAT_U8;
- case AFMT_S16_LE: return SNDRV_PCM_FORMAT_S16_LE;
- case AFMT_S16_BE: return SNDRV_PCM_FORMAT_S16_BE;
- case AFMT_S8: return SNDRV_PCM_FORMAT_S8;
- case AFMT_U16_LE: return SNDRV_PCM_FORMAT_U16_LE;
- case AFMT_U16_BE: return SNDRV_PCM_FORMAT_U16_BE;
- case AFMT_MPEG: return SNDRV_PCM_FORMAT_MPEG;
- case AFMT_S32_LE: return SNDRV_PCM_FORMAT_S32_LE;
- case AFMT_S32_BE: return SNDRV_PCM_FORMAT_S32_BE;
- case AFMT_S24_LE: return SNDRV_PCM_FORMAT_S24_LE;
- case AFMT_S24_BE: return SNDRV_PCM_FORMAT_S24_BE;
- case AFMT_S24_PACKED: return SNDRV_PCM_FORMAT_S24_3LE;
- case AFMT_FLOAT: return SNDRV_PCM_FORMAT_FLOAT;
- case AFMT_SPDIF_RAW: return SNDRV_PCM_FORMAT_IEC958_SUBFRAME;
- default: return SNDRV_PCM_FORMAT_U8;
- }
-}
-
-static int snd_pcm_oss_format_to(snd_pcm_format_t format)
-{
- switch (format) {
- case SNDRV_PCM_FORMAT_MU_LAW: return AFMT_MU_LAW;
- case SNDRV_PCM_FORMAT_A_LAW: return AFMT_A_LAW;
- case SNDRV_PCM_FORMAT_IMA_ADPCM: return AFMT_IMA_ADPCM;
- case SNDRV_PCM_FORMAT_U8: return AFMT_U8;
- case SNDRV_PCM_FORMAT_S16_LE: return AFMT_S16_LE;
- case SNDRV_PCM_FORMAT_S16_BE: return AFMT_S16_BE;
- case SNDRV_PCM_FORMAT_S8: return AFMT_S8;
- case SNDRV_PCM_FORMAT_U16_LE: return AFMT_U16_LE;
- case SNDRV_PCM_FORMAT_U16_BE: return AFMT_U16_BE;
- case SNDRV_PCM_FORMAT_MPEG: return AFMT_MPEG;
- case SNDRV_PCM_FORMAT_S32_LE: return AFMT_S32_LE;
- case SNDRV_PCM_FORMAT_S32_BE: return AFMT_S32_BE;
- case SNDRV_PCM_FORMAT_S24_LE: return AFMT_S24_LE;
- case SNDRV_PCM_FORMAT_S24_BE: return AFMT_S24_BE;
- case SNDRV_PCM_FORMAT_S24_3LE: return AFMT_S24_PACKED;
- case SNDRV_PCM_FORMAT_FLOAT: return AFMT_FLOAT;
- case SNDRV_PCM_FORMAT_IEC958_SUBFRAME: return AFMT_SPDIF_RAW;
- default: return -EINVAL;
- }
-}
-
-static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *oss_params,
- struct snd_pcm_hw_params *slave_params)
-{
- size_t s;
- size_t oss_buffer_size, oss_period_size, oss_periods;
- size_t min_period_size, max_period_size;
- struct snd_pcm_runtime *runtime = substream->runtime;
- size_t oss_frame_size;
-
- oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) *
- params_channels(oss_params) / 8;
-
- oss_buffer_size = snd_pcm_plug_client_size(substream,
- snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size;
- oss_buffer_size = 1 << ld2(oss_buffer_size);
- if (atomic_read(&substream->mmap_count)) {
- if (oss_buffer_size > runtime->oss.mmap_bytes)
- oss_buffer_size = runtime->oss.mmap_bytes;
- }
-
- if (substream->oss.setup.period_size > 16)
- oss_period_size = substream->oss.setup.period_size;
- else if (runtime->oss.fragshift) {
- oss_period_size = 1 << runtime->oss.fragshift;
- if (oss_period_size > oss_buffer_size / 2)
- oss_period_size = oss_buffer_size / 2;
- } else {
- int sd;
- size_t bytes_per_sec = params_rate(oss_params) * snd_pcm_format_physical_width(params_format(oss_params)) * params_channels(oss_params) / 8;
-
- oss_period_size = oss_buffer_size;
- do {
- oss_period_size /= 2;
- } while (oss_period_size > bytes_per_sec);
- if (runtime->oss.subdivision == 0) {
- sd = 4;
- if (oss_period_size / sd > 4096)
- sd *= 2;
- if (oss_period_size / sd < 4096)
- sd = 1;
- } else
- sd = runtime->oss.subdivision;
- oss_period_size /= sd;
- if (oss_period_size < 16)
- oss_period_size = 16;
- }
-
- min_period_size = snd_pcm_plug_client_size(substream,
- snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
- min_period_size *= oss_frame_size;
- min_period_size = 1 << (ld2(min_period_size - 1) + 1);
- if (oss_period_size < min_period_size)
- oss_period_size = min_period_size;
-
- max_period_size = snd_pcm_plug_client_size(substream,
- snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
- max_period_size *= oss_frame_size;
- max_period_size = 1 << ld2(max_period_size);
- if (oss_period_size > max_period_size)
- oss_period_size = max_period_size;
-
- oss_periods = oss_buffer_size / oss_period_size;
-
- if (substream->oss.setup.periods > 1)
- oss_periods = substream->oss.setup.periods;
-
- s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
- if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
- s = runtime->oss.maxfrags;
- if (oss_periods > s)
- oss_periods = s;
-
- s = snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
- if (s < 2)
- s = 2;
- if (oss_periods < s)
- oss_periods = s;
-
- while (oss_period_size * oss_periods > oss_buffer_size)
- oss_period_size /= 2;
-
- if (oss_period_size < 16)
- return -EINVAL;
- runtime->oss.period_bytes = oss_period_size;
- runtime->oss.period_frames = 1;
- runtime->oss.periods = oss_periods;
- return 0;
-}
-
-static int choose_rate(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params, unsigned int best_rate)
-{
- struct snd_interval *it;
- struct snd_pcm_hw_params *save;
- unsigned int rate, prev;
-
- save = kmalloc(sizeof(*save), GFP_KERNEL);
- if (save == NULL)
- return -ENOMEM;
- *save = *params;
- it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE);
-
- /* try multiples of the best rate */
- rate = best_rate;
- for (;;) {
- if (it->max < rate || (it->max == rate && it->openmax))
- break;
- if (it->min < rate || (it->min == rate && !it->openmin)) {
- int ret;
- ret = snd_pcm_hw_param_set(substream, params,
- SNDRV_PCM_HW_PARAM_RATE,
- rate, 0);
- if (ret == (int)rate) {
- kfree(save);
- return rate;
- }
- *params = *save;
- }
- prev = rate;
- rate += best_rate;
- if (rate <= prev)
- break;
- }
-
- /* not found, use the nearest rate */
- kfree(save);
- return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
-}
-
-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_pcm_hw_params *params, *sparams;
- struct snd_pcm_sw_params *sw_params;
- ssize_t oss_buffer_size, oss_period_size;
- size_t oss_frame_size;
- int err;
- int direct;
- snd_pcm_format_t format, sformat;
- int n;
- struct snd_mask sformat_mask;
- struct snd_mask mask;
-
- if (mutex_lock_interruptible(&runtime->oss.params_lock))
- return -EINTR;
- sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
- if (!sw_params || !params || !sparams) {
- snd_printd("No memory\n");
- err = -ENOMEM;
- goto failure;
- }
-
- if (atomic_read(&substream->mmap_count))
- direct = 1;
- else
- direct = substream->oss.setup.direct;
-
- _snd_pcm_hw_params_any(sparams);
- _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
- _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
- snd_mask_none(&mask);
- if (atomic_read(&substream->mmap_count))
- snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
- else {
- snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED);
- if (!direct)
- snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
- }
- err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask);
- if (err < 0) {
- snd_printd("No usable accesses\n");
- err = -EINVAL;
- goto failure;
- }
- choose_rate(substream, sparams, runtime->oss.rate);
- snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL);
-
- format = snd_pcm_oss_format_from(runtime->oss.format);
-
- sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
- if (direct)
- sformat = format;
- else
- sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
-
- if ((__force int)sformat < 0 ||
- !snd_mask_test(&sformat_mask, (__force int)sformat)) {
- for (sformat = (__force snd_pcm_format_t)0;
- (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST;
- sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) {
- if (snd_mask_test(&sformat_mask, (__force int)sformat) &&
- snd_pcm_oss_format_to(sformat) >= 0)
- break;
- }
- if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) {
- snd_printd("Cannot find a format!!!\n");
- err = -EINVAL;
- goto failure;
- }
- }
- err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0);
- if (err < 0)
- goto failure;
-
- if (direct) {
- memcpy(params, sparams, sizeof(*params));
- } else {
- _snd_pcm_hw_params_any(params);
- _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
- (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
- _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
- (__force int)snd_pcm_oss_format_from(runtime->oss.format), 0);
- _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
- runtime->oss.channels, 0);
- _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
- runtime->oss.rate, 0);
- pdprintf("client: access = %i, format = %i, channels = %i, rate = %i\n",
- params_access(params), params_format(params),
- params_channels(params), params_rate(params));
- }
- pdprintf("slave: access = %i, format = %i, channels = %i, rate = %i\n",
- params_access(sparams), params_format(sparams),
- params_channels(sparams), params_rate(sparams));
-
- oss_frame_size = snd_pcm_format_physical_width(params_format(params)) *
- params_channels(params) / 8;
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
- snd_pcm_oss_plugin_clear(substream);
- if (!direct) {
- /* add necessary plugins */
- snd_pcm_oss_plugin_clear(substream);
- if ((err = snd_pcm_plug_format_plugins(substream,
- params,
- sparams)) < 0) {
- snd_printd("snd_pcm_plug_format_plugins failed: %i\n", err);
- snd_pcm_oss_plugin_clear(substream);
- goto failure;
- }
- if (runtime->oss.plugin_first) {
- struct snd_pcm_plugin *plugin;
- if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) {
- snd_printd("snd_pcm_plugin_build_io failed: %i\n", err);
- snd_pcm_oss_plugin_clear(substream);
- goto failure;
- }
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- err = snd_pcm_plugin_append(plugin);
- } else {
- err = snd_pcm_plugin_insert(plugin);
- }
- if (err < 0) {
- snd_pcm_oss_plugin_clear(substream);
- goto failure;
- }
- }
- }
-#endif
-
- err = snd_pcm_oss_period_size(substream, params, sparams);
- if (err < 0)
- goto failure;
-
- n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size);
- err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL);
- if (err < 0)
- goto failure;
-
- err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS,
- runtime->oss.periods, NULL);
- if (err < 0)
- goto failure;
-
- snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
-
- if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) {
- snd_printd("HW_PARAMS failed: %i\n", err);
- goto failure;
- }
-
- memset(sw_params, 0, sizeof(*sw_params));
- if (runtime->oss.trigger) {
- sw_params->start_threshold = 1;
- } else {
- sw_params->start_threshold = runtime->boundary;
- }
- if (atomic_read(&substream->mmap_count) ||
- substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- sw_params->stop_threshold = runtime->boundary;
- else
- sw_params->stop_threshold = runtime->buffer_size;
- sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
- sw_params->period_step = 1;
- sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- 1 : runtime->period_size;
- if (atomic_read(&substream->mmap_count) ||
- substream->oss.setup.nosilence) {
- sw_params->silence_threshold = 0;
- sw_params->silence_size = 0;
- } else {
- snd_pcm_uframes_t frames;
- frames = runtime->period_size + 16;
- if (frames > runtime->buffer_size)
- frames = runtime->buffer_size;
- sw_params->silence_threshold = frames;
- sw_params->silence_size = frames;
- }
-
- if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) {
- snd_printd("SW_PARAMS failed: %i\n", err);
- goto failure;
- }
-
- runtime->oss.periods = params_periods(sparams);
- oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams));
- if (oss_period_size < 0) {
- err = -EINVAL;
- goto failure;
- }
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
- if (runtime->oss.plugin_first) {
- err = snd_pcm_plug_alloc(substream, oss_period_size);
- if (err < 0)
- goto failure;
- }
-#endif
- oss_period_size *= oss_frame_size;
-
- oss_buffer_size = oss_period_size * runtime->oss.periods;
- if (oss_buffer_size < 0) {
- err = -EINVAL;
- goto failure;
- }
-
- runtime->oss.period_bytes = oss_period_size;
- runtime->oss.buffer_bytes = oss_buffer_size;
-
- pdprintf("oss: period bytes = %i, buffer bytes = %i\n",
- runtime->oss.period_bytes,
- runtime->oss.buffer_bytes);
- pdprintf("slave: period_size = %i, buffer_size = %i\n",
- params_period_size(sparams),
- params_buffer_size(sparams));
-
- runtime->oss.format = snd_pcm_oss_format_to(params_format(params));
- runtime->oss.channels = params_channels(params);
- runtime->oss.rate = params_rate(params);
-
- vfree(runtime->oss.buffer);
- runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);
- if (!runtime->oss.buffer) {
- err = -ENOMEM;
- goto failure;
- }
-
- runtime->oss.params = 0;
- runtime->oss.prepare = 1;
- runtime->oss.buffer_used = 0;
- if (runtime->dma_area)
- snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
-
- runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size);
-
- err = 0;
-failure:
- kfree(sw_params);
- kfree(params);
- kfree(sparams);
- mutex_unlock(&runtime->oss.params_lock);
- return err;
-}
-
-static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_file, struct snd_pcm_substream **r_substream)
-{
- int idx, err;
- struct snd_pcm_substream *asubstream = NULL, *substream;
-
- for (idx = 0; idx < 2; idx++) {
- substream = pcm_oss_file->streams[idx];
- if (substream == NULL)
- continue;
- if (asubstream == NULL)
- asubstream = substream;
- if (substream->runtime->oss.params) {
- err = snd_pcm_oss_change_params(substream);
- if (err < 0)
- return err;
- }
- }
- if (!asubstream)
- return -EIO;
- if (r_substream)
- *r_substream = asubstream;
- return 0;
-}
-
-static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream)
-{
- int err;
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
- if (err < 0) {
- snd_printd("snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n");
- return err;
- }
- runtime->oss.prepare = 0;
- runtime->oss.prev_hw_ptr_period = 0;
- runtime->oss.period_ptr = 0;
- runtime->oss.buffer_used = 0;
-
- return 0;
-}
-
-static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
- int err;
-
- if (substream == NULL)
- return 0;
- runtime = substream->runtime;
- if (runtime->oss.params) {
- err = snd_pcm_oss_change_params(substream);
- if (err < 0)
- return err;
- }
- if (runtime->oss.prepare) {
- err = snd_pcm_oss_prepare(substream);
- if (err < 0)
- return err;
- }
- return 0;
-}
-
-static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substream, snd_pcm_sframes_t *delay)
-{
- struct snd_pcm_runtime *runtime;
- snd_pcm_uframes_t frames;
- int err = 0;
-
- while (1) {
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, delay);
- if (err < 0)
- break;
- runtime = substream->runtime;
- if (*delay <= (snd_pcm_sframes_t)runtime->buffer_size)
- break;
- /* in case of overrun, skip whole periods like OSS/Linux driver does */
- /* until avail(delay) <= buffer_size */
- frames = (*delay - runtime->buffer_size) + runtime->period_size - 1;
- frames /= runtime->period_size;
- frames *= runtime->period_size;
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_FORWARD, &frames);
- if (err < 0)
- break;
- }
- return err;
-}
-
-snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int ret;
- while (1) {
- if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
-#ifdef OSS_DEBUG
- if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
- printk(KERN_DEBUG "pcm_oss: write: "
- "recovering from XRUN\n");
- else
- printk(KERN_DEBUG "pcm_oss: write: "
- "recovering from SUSPEND\n");
-#endif
- ret = snd_pcm_oss_prepare(substream);
- if (ret < 0)
- break;
- }
- if (in_kernel) {
- mm_segment_t fs;
- fs = snd_enter_user();
- ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
- snd_leave_user(fs);
- } else {
- ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
- }
- if (ret != -EPIPE && ret != -ESTRPIPE)
- break;
- /* test, if we can't store new data, because the stream */
- /* has not been started */
- if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
- return -EAGAIN;
- }
- return ret;
-}
-
-snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t delay;
- int ret;
- while (1) {
- if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
-#ifdef OSS_DEBUG
- if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
- printk(KERN_DEBUG "pcm_oss: read: "
- "recovering from XRUN\n");
- else
- printk(KERN_DEBUG "pcm_oss: read: "
- "recovering from SUSPEND\n");
-#endif
- ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
- if (ret < 0)
- break;
- } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
- ret = snd_pcm_oss_prepare(substream);
- if (ret < 0)
- break;
- }
- ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
- if (ret < 0)
- break;
- if (in_kernel) {
- mm_segment_t fs;
- fs = snd_enter_user();
- ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
- snd_leave_user(fs);
- } else {
- ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
- }
- if (ret == -EPIPE) {
- if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
- ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
- if (ret < 0)
- break;
- }
- continue;
- }
- if (ret != -ESTRPIPE)
- break;
- }
- return ret;
-}
-
-snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int ret;
- while (1) {
- if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
-#ifdef OSS_DEBUG
- if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
- printk(KERN_DEBUG "pcm_oss: writev: "
- "recovering from XRUN\n");
- else
- printk(KERN_DEBUG "pcm_oss: writev: "
- "recovering from SUSPEND\n");
-#endif
- ret = snd_pcm_oss_prepare(substream);
- if (ret < 0)
- break;
- }
- if (in_kernel) {
- mm_segment_t fs;
- fs = snd_enter_user();
- ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
- snd_leave_user(fs);
- } else {
- ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
- }
- if (ret != -EPIPE && ret != -ESTRPIPE)
- break;
-
- /* test, if we can't store new data, because the stream */
- /* has not been started */
- if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
- return -EAGAIN;
- }
- return ret;
-}
-
-snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int ret;
- while (1) {
- if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
-#ifdef OSS_DEBUG
- if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
- printk(KERN_DEBUG "pcm_oss: readv: "
- "recovering from XRUN\n");
- else
- printk(KERN_DEBUG "pcm_oss: readv: "
- "recovering from SUSPEND\n");
-#endif
- ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
- if (ret < 0)
- break;
- } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
- ret = snd_pcm_oss_prepare(substream);
- if (ret < 0)
- break;
- }
- if (in_kernel) {
- mm_segment_t fs;
- fs = snd_enter_user();
- ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
- snd_leave_user(fs);
- } else {
- ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
- }
- if (ret != -EPIPE && ret != -ESTRPIPE)
- break;
- }
- return ret;
-}
-
-static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t frames, frames1;
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
- if (runtime->oss.plugin_first) {
- struct snd_pcm_plugin_channel *channels;
- size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
- if (!in_kernel) {
- if (copy_from_user(runtime->oss.buffer, (const char __force __user *)buf, bytes))
- return -EFAULT;
- buf = runtime->oss.buffer;
- }
- frames = bytes / oss_frame_bytes;
- frames1 = snd_pcm_plug_client_channels_buf(substream, (char *)buf, frames, &channels);
- if (frames1 < 0)
- return frames1;
- frames1 = snd_pcm_plug_write_transfer(substream, channels, frames1);
- if (frames1 <= 0)
- return frames1;
- bytes = frames1 * oss_frame_bytes;
- } else
-#endif
- {
- frames = bytes_to_frames(runtime, bytes);
- frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel);
- if (frames1 <= 0)
- return frames1;
- bytes = frames_to_bytes(runtime, frames1);
- }
- return bytes;
-}
-
-static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes)
-{
- size_t xfer = 0;
- ssize_t tmp;
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- if (atomic_read(&substream->mmap_count))
- return -ENXIO;
-
- if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
- return tmp;
- mutex_lock(&runtime->oss.params_lock);
- while (bytes > 0) {
- if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
- tmp = bytes;
- if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
- tmp = runtime->oss.period_bytes - runtime->oss.buffer_used;
- if (tmp > 0) {
- if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) {
- tmp = -EFAULT;
- goto err;
- }
- }
- runtime->oss.buffer_used += tmp;
- buf += tmp;
- bytes -= tmp;
- xfer += tmp;
- if (substream->oss.setup.partialfrag ||
- runtime->oss.buffer_used == runtime->oss.period_bytes) {
- tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr,
- runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
- if (tmp <= 0)
- goto err;
- runtime->oss.bytes += tmp;
- runtime->oss.period_ptr += tmp;
- runtime->oss.period_ptr %= runtime->oss.period_bytes;
- if (runtime->oss.period_ptr == 0 ||
- runtime->oss.period_ptr == runtime->oss.buffer_used)
- runtime->oss.buffer_used = 0;
- else if ((substream->f_flags & O_NONBLOCK) != 0) {
- tmp = -EAGAIN;
- goto err;
- }
- }
- } else {
- tmp = snd_pcm_oss_write2(substream,
- (const char __force *)buf,
- runtime->oss.period_bytes, 0);
- if (tmp <= 0)
- goto err;
- runtime->oss.bytes += tmp;
- buf += tmp;
- bytes -= tmp;
- xfer += tmp;
- if ((substream->f_flags & O_NONBLOCK) != 0 &&
- tmp != runtime->oss.period_bytes)
- break;
- }
- }
- mutex_unlock(&runtime->oss.params_lock);
- return xfer;
-
- err:
- mutex_unlock(&runtime->oss.params_lock);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
-}
-
-static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t frames, frames1;
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
- char __user *final_dst = (char __force __user *)buf;
- if (runtime->oss.plugin_first) {
- struct snd_pcm_plugin_channel *channels;
- size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
- if (!in_kernel)
- buf = runtime->oss.buffer;
- frames = bytes / oss_frame_bytes;
- frames1 = snd_pcm_plug_client_channels_buf(substream, buf, frames, &channels);
- if (frames1 < 0)
- return frames1;
- frames1 = snd_pcm_plug_read_transfer(substream, channels, frames1);
- if (frames1 <= 0)
- return frames1;
- bytes = frames1 * oss_frame_bytes;
- if (!in_kernel && copy_to_user(final_dst, buf, bytes))
- return -EFAULT;
- } else
-#endif
- {
- frames = bytes_to_frames(runtime, bytes);
- frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);
- if (frames1 <= 0)
- return frames1;
- bytes = frames_to_bytes(runtime, frames1);
- }
- return bytes;
-}
-
-static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes)
-{
- size_t xfer = 0;
- ssize_t tmp;
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- if (atomic_read(&substream->mmap_count))
- return -ENXIO;
-
- if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
- return tmp;
- mutex_lock(&runtime->oss.params_lock);
- while (bytes > 0) {
- if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
- if (runtime->oss.buffer_used == 0) {
- tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
- if (tmp <= 0)
- goto err;
- runtime->oss.bytes += tmp;
- runtime->oss.period_ptr = tmp;
- runtime->oss.buffer_used = tmp;
- }
- tmp = bytes;
- if ((size_t) tmp > runtime->oss.buffer_used)
- tmp = runtime->oss.buffer_used;
- if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp)) {
- tmp = -EFAULT;
- goto err;
- }
- buf += tmp;
- bytes -= tmp;
- xfer += tmp;
- runtime->oss.buffer_used -= tmp;
- } else {
- tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
- runtime->oss.period_bytes, 0);
- if (tmp <= 0)
- goto err;
- runtime->oss.bytes += tmp;
- buf += tmp;
- bytes -= tmp;
- xfer += tmp;
- }
- }
- mutex_unlock(&runtime->oss.params_lock);
- return xfer;
-
- err:
- mutex_unlock(&runtime->oss.params_lock);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
-}
-
-static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
-{
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- int i;
-
- for (i = 0; i < 2; i++) {
- substream = pcm_oss_file->streams[i];
- if (!substream)
- continue;
- runtime = substream->runtime;
- snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
- runtime->oss.prepare = 1;
- runtime->oss.buffer_used = 0;
- runtime->oss.prev_hw_ptr_period = 0;
- runtime->oss.period_ptr = 0;
- }
- return 0;
-}
-
-static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file)
-{
- struct snd_pcm_substream *substream;
- int err;
-
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- if (substream != NULL) {
- if ((err = snd_pcm_oss_make_ready(substream)) < 0)
- return err;
- snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
- }
- /* note: all errors from the start action are ignored */
- /* OSS apps do not know, how to handle them */
- return 0;
-}
-
-static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
-{
- struct snd_pcm_runtime *runtime;
- ssize_t result = 0;
- snd_pcm_state_t state;
- long res;
- wait_queue_t wait;
-
- runtime = substream->runtime;
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&runtime->sleep, &wait);
-#ifdef OSS_DEBUG
- printk(KERN_DEBUG "sync1: size = %li\n", size);
-#endif
- while (1) {
- result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);
- if (result > 0) {
- runtime->oss.buffer_used = 0;
- result = 0;
- break;
- }
- if (result != 0 && result != -EAGAIN)
- break;
- result = 0;
- set_current_state(TASK_INTERRUPTIBLE);
- snd_pcm_stream_lock_irq(substream);
- state = runtime->status->state;
- snd_pcm_stream_unlock_irq(substream);
- if (state != SNDRV_PCM_STATE_RUNNING) {
- set_current_state(TASK_RUNNING);
- break;
- }
- res = schedule_timeout(10 * HZ);
- if (signal_pending(current)) {
- result = -ERESTARTSYS;
- break;
- }
- if (res == 0) {
- snd_printk(KERN_ERR "OSS sync error - DMA timeout\n");
- result = -EIO;
- break;
- }
- }
- remove_wait_queue(&runtime->sleep, &wait);
- return result;
-}
-
-static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
-{
- int err = 0;
- unsigned int saved_f_flags;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- snd_pcm_format_t format;
- unsigned long width;
- size_t size;
-
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- if (substream != NULL) {
- runtime = substream->runtime;
- if (atomic_read(&substream->mmap_count))
- goto __direct;
- if ((err = snd_pcm_oss_make_ready(substream)) < 0)
- return err;
- format = snd_pcm_oss_format_from(runtime->oss.format);
- width = snd_pcm_format_physical_width(format);
- mutex_lock(&runtime->oss.params_lock);
- if (runtime->oss.buffer_used > 0) {
-#ifdef OSS_DEBUG
- printk(KERN_DEBUG "sync: buffer_used\n");
-#endif
- size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;
- snd_pcm_format_set_silence(format,
- runtime->oss.buffer + runtime->oss.buffer_used,
- size);
- err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
- if (err < 0) {
- mutex_unlock(&runtime->oss.params_lock);
- return err;
- }
- } else if (runtime->oss.period_ptr > 0) {
-#ifdef OSS_DEBUG
- printk(KERN_DEBUG "sync: period_ptr\n");
-#endif
- size = runtime->oss.period_bytes - runtime->oss.period_ptr;
- snd_pcm_format_set_silence(format,
- runtime->oss.buffer,
- size * 8 / width);
- err = snd_pcm_oss_sync1(substream, size);
- if (err < 0) {
- mutex_unlock(&runtime->oss.params_lock);
- return err;
- }
- }
- /*
- * The ALSA's period might be a bit large than OSS one.
- * Fill the remain portion of ALSA period with zeros.
- */
- size = runtime->control->appl_ptr % runtime->period_size;
- if (size > 0) {
- size = runtime->period_size - size;
- if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
- size = (runtime->frame_bits * size) / 8;
- while (size > 0) {
- mm_segment_t fs;
- size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
- size -= size1;
- size1 *= 8;
- size1 /= runtime->sample_bits;
- snd_pcm_format_set_silence(runtime->format,
- runtime->oss.buffer,
- size1);
- size1 /= runtime->channels; /* frames */
- fs = snd_enter_user();
- snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1);
- snd_leave_user(fs);
- }
- } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
- void __user *buffers[runtime->channels];
- memset(buffers, 0, runtime->channels * sizeof(void *));
- snd_pcm_lib_writev(substream, buffers, size);
- }
- }
- mutex_unlock(&runtime->oss.params_lock);
- /*
- * finish sync: drain the buffer
- */
- __direct:
- saved_f_flags = substream->f_flags;
- substream->f_flags &= ~O_NONBLOCK;
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
- substream->f_flags = saved_f_flags;
- if (err < 0)
- return err;
- runtime->oss.prepare = 1;
- }
-
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
- if (substream != NULL) {
- if ((err = snd_pcm_oss_make_ready(substream)) < 0)
- return err;
- runtime = substream->runtime;
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
- if (err < 0)
- return err;
- runtime->oss.buffer_used = 0;
- runtime->oss.prepare = 1;
- }
- return 0;
-}
-
-static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate)
-{
- int idx;
-
- for (idx = 1; idx >= 0; --idx) {
- struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
- struct snd_pcm_runtime *runtime;
- if (substream == NULL)
- continue;
- runtime = substream->runtime;
- if (rate < 1000)
- rate = 1000;
- else if (rate > 192000)
- rate = 192000;
- if (runtime->oss.rate != rate) {
- runtime->oss.params = 1;
- runtime->oss.rate = rate;
- }
- }
- return snd_pcm_oss_get_rate(pcm_oss_file);
-}
-
-static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file)
-{
- struct snd_pcm_substream *substream;
- int err;
-
- if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
- return err;
- return substream->runtime->oss.rate;
-}
-
-static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsigned int channels)
-{
- int idx;
- if (channels < 1)
- channels = 1;
- if (channels > 128)
- return -EINVAL;
- for (idx = 1; idx >= 0; --idx) {
- struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
- struct snd_pcm_runtime *runtime;
- if (substream == NULL)
- continue;
- runtime = substream->runtime;
- if (runtime->oss.channels != channels) {
- runtime->oss.params = 1;
- runtime->oss.channels = channels;
- }
- }
- return snd_pcm_oss_get_channels(pcm_oss_file);
-}
-
-static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file)
-{
- struct snd_pcm_substream *substream;
- int err;
-
- if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
- return err;
- return substream->runtime->oss.channels;
-}
-
-static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file)
-{
- struct snd_pcm_substream *substream;
- int err;
-
- if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
- return err;
- return substream->runtime->oss.period_bytes;
-}
-
-static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
-{
- struct snd_pcm_substream *substream;
- int err;
- int direct;
- struct snd_pcm_hw_params *params;
- unsigned int formats = 0;
- struct snd_mask format_mask;
- int fmt;
-
- if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
- return err;
- if (atomic_read(&substream->mmap_count))
- direct = 1;
- else
- direct = substream->oss.setup.direct;
- if (!direct)
- return AFMT_MU_LAW | AFMT_U8 |
- AFMT_S16_LE | AFMT_S16_BE |
- AFMT_S8 | AFMT_U16_LE |
- AFMT_U16_BE |
- AFMT_S32_LE | AFMT_S32_BE |
- AFMT_S24_LE | AFMT_S24_BE |
- AFMT_S24_PACKED;
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params)
- return -ENOMEM;
- _snd_pcm_hw_params_any(params);
- err = snd_pcm_hw_refine(substream, params);
- format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
- kfree(params);
- if (err < 0)
- return err;
- for (fmt = 0; fmt < 32; ++fmt) {
- if (snd_mask_test(&format_mask, fmt)) {
- int f = snd_pcm_oss_format_to(fmt);
- if (f >= 0)
- formats |= f;
- }
- }
- return formats;
-}
-
-static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
-{
- int formats, idx;
-
- if (format != AFMT_QUERY) {
- formats = snd_pcm_oss_get_formats(pcm_oss_file);
- if (formats < 0)
- return formats;
- if (!(formats & format))
- format = AFMT_U8;
- for (idx = 1; idx >= 0; --idx) {
- struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
- struct snd_pcm_runtime *runtime;
- if (substream == NULL)
- continue;
- runtime = substream->runtime;
- if (runtime->oss.format != format) {
- runtime->oss.params = 1;
- runtime->oss.format = format;
- }
- }
- }
- return snd_pcm_oss_get_format(pcm_oss_file);
-}
-
-static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file)
-{
- struct snd_pcm_substream *substream;
- int err;
-
- if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
- return err;
- return substream->runtime->oss.format;
-}
-
-static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int subdivide)
-{
- struct snd_pcm_runtime *runtime;
-
- if (substream == NULL)
- return 0;
- runtime = substream->runtime;
- if (subdivide == 0) {
- subdivide = runtime->oss.subdivision;
- if (subdivide == 0)
- subdivide = 1;
- return subdivide;
- }
- if (runtime->oss.subdivision || runtime->oss.fragshift)
- return -EINVAL;
- if (subdivide != 1 && subdivide != 2 && subdivide != 4 &&
- subdivide != 8 && subdivide != 16)
- return -EINVAL;
- runtime->oss.subdivision = subdivide;
- runtime->oss.params = 1;
- return subdivide;
-}
-
-static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int subdivide)
-{
- int err = -EINVAL, idx;
-
- for (idx = 1; idx >= 0; --idx) {
- struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
- if (substream == NULL)
- continue;
- if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0)
- return err;
- }
- return err;
-}
-
-static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val)
-{
- struct snd_pcm_runtime *runtime;
-
- if (substream == NULL)
- return 0;
- runtime = substream->runtime;
- if (runtime->oss.subdivision || runtime->oss.fragshift)
- return -EINVAL;
- runtime->oss.fragshift = val & 0xffff;
- runtime->oss.maxfrags = (val >> 16) & 0xffff;
- if (runtime->oss.fragshift < 4) /* < 16 */
- runtime->oss.fragshift = 4;
- if (runtime->oss.maxfrags < 2)
- runtime->oss.maxfrags = 2;
- runtime->oss.params = 1;
- return 0;
-}
-
-static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val)
-{
- int err = -EINVAL, idx;
-
- for (idx = 1; idx >= 0; --idx) {
- struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
- if (substream == NULL)
- continue;
- if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0)
- return err;
- }
- return err;
-}
-
-static int snd_pcm_oss_nonblock(struct file * file)
-{
- spin_lock(&file->f_lock);
- file->f_flags |= O_NONBLOCK;
- spin_unlock(&file->f_lock);
- return 0;
-}
-
-static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res)
-{
-
- if (substream == NULL) {
- res &= ~DSP_CAP_DUPLEX;
- return res;
- }
-#ifdef DSP_CAP_MULTI
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- if (substream->pstr->substream_count > 1)
- res |= DSP_CAP_MULTI;
-#endif
- /* DSP_CAP_REALTIME is set all times: */
- /* all ALSA drivers can return actual pointer in ring buffer */
-#if defined(DSP_CAP_REALTIME) && 0
- {
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH))
- res &= ~DSP_CAP_REALTIME;
- }
-#endif
- return res;
-}
-
-static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file)
-{
- int result, idx;
-
- result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME;
- for (idx = 0; idx < 2; idx++) {
- struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
- result = snd_pcm_oss_get_caps1(substream, result);
- }
- result |= 0x0001; /* revision - same as SB AWE 64 */
- return result;
-}
-
-static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t hw_ptr)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_uframes_t appl_ptr;
- appl_ptr = hw_ptr + runtime->buffer_size;
- appl_ptr %= runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
-}
-
-static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger)
-{
- struct snd_pcm_runtime *runtime;
- struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
- int err, cmd;
-
-#ifdef OSS_DEBUG
- printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger);
-#endif
-
- psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
-
- if (psubstream) {
- if ((err = snd_pcm_oss_make_ready(psubstream)) < 0)
- return err;
- }
- if (csubstream) {
- if ((err = snd_pcm_oss_make_ready(csubstream)) < 0)
- return err;
- }
- if (psubstream) {
- runtime = psubstream->runtime;
- if (trigger & PCM_ENABLE_OUTPUT) {
- if (runtime->oss.trigger)
- goto _skip1;
- if (atomic_read(&psubstream->mmap_count))
- snd_pcm_oss_simulate_fill(psubstream,
- get_hw_ptr_period(runtime));
- runtime->oss.trigger = 1;
- runtime->start_threshold = 1;
- cmd = SNDRV_PCM_IOCTL_START;
- } else {
- if (!runtime->oss.trigger)
- goto _skip1;
- runtime->oss.trigger = 0;
- runtime->start_threshold = runtime->boundary;
- cmd = SNDRV_PCM_IOCTL_DROP;
- runtime->oss.prepare = 1;
- }
- err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
- if (err < 0)
- return err;
- }
- _skip1:
- if (csubstream) {
- runtime = csubstream->runtime;
- if (trigger & PCM_ENABLE_INPUT) {
- if (runtime->oss.trigger)
- goto _skip2;
- runtime->oss.trigger = 1;
- runtime->start_threshold = 1;
- cmd = SNDRV_PCM_IOCTL_START;
- } else {
- if (!runtime->oss.trigger)
- goto _skip2;
- runtime->oss.trigger = 0;
- runtime->start_threshold = runtime->boundary;
- cmd = SNDRV_PCM_IOCTL_DROP;
- runtime->oss.prepare = 1;
- }
- err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
- if (err < 0)
- return err;
- }
- _skip2:
- return 0;
-}
-
-static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
-{
- struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
- int result = 0;
-
- psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
- if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
- result |= PCM_ENABLE_OUTPUT;
- if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
- result |= PCM_ENABLE_INPUT;
- return result;
-}
-
-static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file)
-{
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- snd_pcm_sframes_t delay;
- int err;
-
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- if (substream == NULL)
- return -EINVAL;
- if ((err = snd_pcm_oss_make_ready(substream)) < 0)
- return err;
- runtime = substream->runtime;
- if (runtime->oss.params || runtime->oss.prepare)
- return 0;
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
- if (err == -EPIPE)
- delay = 0; /* hack for broken OSS applications */
- else if (err < 0)
- return err;
- return snd_pcm_oss_bytes(substream, delay);
-}
-
-static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info)
-{
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- snd_pcm_sframes_t delay;
- int fixup;
- struct count_info info;
- int err;
-
- if (_info == NULL)
- return -EFAULT;
- substream = pcm_oss_file->streams[stream];
- if (substream == NULL)
- return -EINVAL;
- if ((err = snd_pcm_oss_make_ready(substream)) < 0)
- return err;
- runtime = substream->runtime;
- if (runtime->oss.params || runtime->oss.prepare) {
- memset(&info, 0, sizeof(info));
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
- if (err == -EPIPE || err == -ESTRPIPE || (! err && delay < 0)) {
- err = 0;
- delay = 0;
- fixup = 0;
- } else {
- fixup = runtime->oss.buffer_used;
- }
- } else {
- err = snd_pcm_oss_capture_position_fixup(substream, &delay);
- fixup = -runtime->oss.buffer_used;
- }
- if (err < 0)
- return err;
- info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
- if (atomic_read(&substream->mmap_count)) {
- snd_pcm_sframes_t n;
- delay = get_hw_ptr_period(runtime);
- n = delay - runtime->oss.prev_hw_ptr_period;
- if (n < 0)
- n += runtime->boundary;
- info.blocks = n / runtime->period_size;
- runtime->oss.prev_hw_ptr_period = delay;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_pcm_oss_simulate_fill(substream, delay);
- info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
- } else {
- delay = snd_pcm_oss_bytes(substream, delay);
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if (substream->oss.setup.buggyptr)
- info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
- else
- info.blocks = (delay + fixup) / runtime->oss.period_bytes;
- info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
- } else {
- delay += fixup;
- info.blocks = delay / runtime->oss.period_bytes;
- info.bytes = (runtime->oss.bytes + delay) & INT_MAX;
- }
- }
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info)
-{
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- snd_pcm_sframes_t avail;
- int fixup;
- struct audio_buf_info info;
- int err;
-
- if (_info == NULL)
- return -EFAULT;
- substream = pcm_oss_file->streams[stream];
- if (substream == NULL)
- return -EINVAL;
- runtime = substream->runtime;
-
- if (runtime->oss.params &&
- (err = snd_pcm_oss_change_params(substream)) < 0)
- return err;
-
- info.fragsize = runtime->oss.period_bytes;
- info.fragstotal = runtime->periods;
- if (runtime->oss.prepare) {
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- info.bytes = runtime->oss.period_bytes * runtime->oss.periods;
- info.fragments = runtime->oss.periods;
- } else {
- info.bytes = 0;
- info.fragments = 0;
- }
- } else {
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail);
- if (err == -EPIPE || err == -ESTRPIPE || (! err && avail < 0)) {
- avail = runtime->buffer_size;
- err = 0;
- fixup = 0;
- } else {
- avail = runtime->buffer_size - avail;
- fixup = -runtime->oss.buffer_used;
- }
- } else {
- err = snd_pcm_oss_capture_position_fixup(substream, &avail);
- fixup = runtime->oss.buffer_used;
- }
- if (err < 0)
- return err;
- info.bytes = snd_pcm_oss_bytes(substream, avail) + fixup;
- info.fragments = info.bytes / runtime->oss.period_bytes;
- }
-
-#ifdef OSS_DEBUG
- printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, "
- "fragstotal = %i, fragsize = %i\n",
- info.bytes, info.fragments, info.fragstotal, info.fragsize);
-#endif
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info)
-{
- // it won't be probably implemented
- // snd_printd("TODO: snd_pcm_oss_get_mapbuf\n");
- return -EINVAL;
-}
-
-static const char *strip_task_path(const char *path)
-{
- const char *ptr, *ptrl = NULL;
- for (ptr = path; *ptr; ptr++) {
- if (*ptr == '/')
- ptrl = ptr + 1;
- }
- return ptrl;
-}
-
-static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
- const char *task_name,
- struct snd_pcm_oss_setup *rsetup)
-{
- struct snd_pcm_oss_setup *setup;
-
- mutex_lock(&pcm->streams[stream].oss.setup_mutex);
- do {
- for (setup = pcm->streams[stream].oss.setup_list; setup;
- setup = setup->next) {
- if (!strcmp(setup->task_name, task_name))
- goto out;
- }
- } while ((task_name = strip_task_path(task_name)) != NULL);
- out:
- if (setup)
- *rsetup = *setup;
- mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
-}
-
-static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
- runtime = substream->runtime;
- vfree(runtime->oss.buffer);
- runtime->oss.buffer = NULL;
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
- snd_pcm_oss_plugin_clear(substream);
-#endif
- substream->oss.oss = 0;
-}
-
-static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
- struct snd_pcm_oss_setup *setup,
- int minor)
-{
- struct snd_pcm_runtime *runtime;
-
- substream->oss.oss = 1;
- substream->oss.setup = *setup;
- if (setup->nonblock)
- substream->f_flags |= O_NONBLOCK;
- else if (setup->block)
- substream->f_flags &= ~O_NONBLOCK;
- runtime = substream->runtime;
- runtime->oss.params = 1;
- runtime->oss.trigger = 1;
- runtime->oss.rate = 8000;
- mutex_init(&runtime->oss.params_lock);
- switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
- case SNDRV_MINOR_OSS_PCM_8:
- runtime->oss.format = AFMT_U8;
- break;
- case SNDRV_MINOR_OSS_PCM_16:
- runtime->oss.format = AFMT_S16_LE;
- break;
- default:
- runtime->oss.format = AFMT_MU_LAW;
- }
- runtime->oss.channels = 1;
- runtime->oss.fragshift = 0;
- runtime->oss.maxfrags = 0;
- runtime->oss.subdivision = 0;
- substream->pcm_release = snd_pcm_oss_release_substream;
-}
-
-static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
-{
- int cidx;
- if (!pcm_oss_file)
- return 0;
- for (cidx = 0; cidx < 2; ++cidx) {
- struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
- if (substream)
- snd_pcm_release_substream(substream);
- }
- kfree(pcm_oss_file);
- return 0;
-}
-
-static int snd_pcm_oss_open_file(struct file *file,
- struct snd_pcm *pcm,
- struct snd_pcm_oss_file **rpcm_oss_file,
- int minor,
- struct snd_pcm_oss_setup *setup)
-{
- int idx, err;
- struct snd_pcm_oss_file *pcm_oss_file;
- struct snd_pcm_substream *substream;
- fmode_t f_mode = file->f_mode;
-
- if (rpcm_oss_file)
- *rpcm_oss_file = NULL;
-
- pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);
- if (pcm_oss_file == NULL)
- return -ENOMEM;
-
- if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
- (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
- f_mode = FMODE_WRITE;
-
- file->f_flags &= ~O_APPEND;
- for (idx = 0; idx < 2; idx++) {
- if (setup[idx].disable)
- continue;
- if (! pcm->streams[idx].substream_count)
- continue; /* no matching substream */
- if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
- if (! (f_mode & FMODE_WRITE))
- continue;
- } else {
- if (! (f_mode & FMODE_READ))
- continue;
- }
- err = snd_pcm_open_substream(pcm, idx, file, &substream);
- if (err < 0) {
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
-
- pcm_oss_file->streams[idx] = substream;
- substream->file = pcm_oss_file;
- snd_pcm_oss_init_substream(substream, &setup[idx], minor);
- }
-
- if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {
- snd_pcm_oss_release_file(pcm_oss_file);
- return -EINVAL;
- }
-
- file->private_data = pcm_oss_file;
- if (rpcm_oss_file)
- *rpcm_oss_file = pcm_oss_file;
- return 0;
-}
-
-
-static int snd_task_name(struct task_struct *task, char *name, size_t size)
-{
- unsigned int idx;
-
- if (snd_BUG_ON(!task || !name || size < 2))
- return -EINVAL;
- for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++)
- name[idx] = task->comm[idx];
- name[idx] = '\0';
- return 0;
-}
-
-static int snd_pcm_oss_open(struct inode *inode, struct file *file)
-{
- int err;
- char task_name[32];
- struct snd_pcm *pcm;
- struct snd_pcm_oss_file *pcm_oss_file;
- struct snd_pcm_oss_setup setup[2];
- int nonblock;
- wait_queue_t wait;
-
- err = nonseekable_open(inode, file);
- if (err < 0)
- return err;
-
- pcm = snd_lookup_oss_minor_data(iminor(inode),
- SNDRV_OSS_DEVICE_TYPE_PCM);
- if (pcm == NULL) {
- err = -ENODEV;
- goto __error1;
- }
- err = snd_card_file_add(pcm->card, file);
- if (err < 0)
- goto __error1;
- if (!try_module_get(pcm->card->module)) {
- err = -EFAULT;
- goto __error2;
- }
- if (snd_task_name(current, task_name, sizeof(task_name)) < 0) {
- err = -EFAULT;
- goto __error;
- }
- memset(setup, 0, sizeof(setup));
- if (file->f_mode & FMODE_WRITE)
- snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- task_name, &setup[0]);
- if (file->f_mode & FMODE_READ)
- snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE,
- task_name, &setup[1]);
-
- nonblock = !!(file->f_flags & O_NONBLOCK);
- if (!nonblock)
- nonblock = nonblock_open;
-
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&pcm->open_wait, &wait);
- mutex_lock(&pcm->open_mutex);
- while (1) {
- err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
- iminor(inode), setup);
- if (err >= 0)
- break;
- if (err == -EAGAIN) {
- if (nonblock) {
- err = -EBUSY;
- break;
- }
- } else
- break;
- set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&pcm->open_mutex);
- schedule();
- mutex_lock(&pcm->open_mutex);
- if (pcm->card->shutdown) {
- err = -ENODEV;
- break;
- }
- if (signal_pending(current)) {
- err = -ERESTARTSYS;
- break;
- }
- }
- remove_wait_queue(&pcm->open_wait, &wait);
- mutex_unlock(&pcm->open_mutex);
- if (err < 0)
- goto __error;
- snd_card_unref(pcm->card);
- return err;
-
- __error:
- module_put(pcm->card->module);
- __error2:
- snd_card_file_remove(pcm->card, file);
- __error1:
- if (pcm)
- snd_card_unref(pcm->card);
- return err;
-}
-
-static int snd_pcm_oss_release(struct inode *inode, struct file *file)
-{
- struct snd_pcm *pcm;
- struct snd_pcm_substream *substream;
- struct snd_pcm_oss_file *pcm_oss_file;
-
- pcm_oss_file = file->private_data;
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- if (substream == NULL)
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
- if (snd_BUG_ON(!substream))
- return -ENXIO;
- pcm = substream->pcm;
- if (!pcm->card->shutdown)
- snd_pcm_oss_sync(pcm_oss_file);
- mutex_lock(&pcm->open_mutex);
- snd_pcm_oss_release_file(pcm_oss_file);
- mutex_unlock(&pcm->open_mutex);
- wake_up(&pcm->open_wait);
- module_put(pcm->card->module);
- snd_card_file_remove(pcm->card, file);
- return 0;
-}
-
-static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct snd_pcm_oss_file *pcm_oss_file;
- int __user *p = (int __user *)arg;
- int res;
-
- pcm_oss_file = file->private_data;
- if (cmd == OSS_GETVERSION)
- return put_user(SNDRV_OSS_VERSION, p);
- if (cmd == OSS_ALSAEMULVER)
- return put_user(1, p);
-#if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE))
- if (((cmd >> 8) & 0xff) == 'M') { /* mixer ioctl - for OSS compatibility */
- struct snd_pcm_substream *substream;
- int idx;
- for (idx = 0; idx < 2; ++idx) {
- substream = pcm_oss_file->streams[idx];
- if (substream != NULL)
- break;
- }
- if (snd_BUG_ON(idx >= 2))
- return -ENXIO;
- return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg);
- }
-#endif
- if (((cmd >> 8) & 0xff) != 'P')
- return -EINVAL;
-#ifdef OSS_DEBUG
- printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd);
-#endif
- switch (cmd) {
- case SNDCTL_DSP_RESET:
- return snd_pcm_oss_reset(pcm_oss_file);
- case SNDCTL_DSP_SYNC:
- return snd_pcm_oss_sync(pcm_oss_file);
- case SNDCTL_DSP_SPEED:
- if (get_user(res, p))
- return -EFAULT;
- if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0)
- return res;
- return put_user(res, p);
- case SOUND_PCM_READ_RATE:
- res = snd_pcm_oss_get_rate(pcm_oss_file);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SNDCTL_DSP_STEREO:
- if (get_user(res, p))
- return -EFAULT;
- res = res > 0 ? 2 : 1;
- if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0)
- return res;
- return put_user(--res, p);
- case SNDCTL_DSP_GETBLKSIZE:
- res = snd_pcm_oss_get_block_size(pcm_oss_file);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SNDCTL_DSP_SETFMT:
- if (get_user(res, p))
- return -EFAULT;
- res = snd_pcm_oss_set_format(pcm_oss_file, res);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SOUND_PCM_READ_BITS:
- res = snd_pcm_oss_get_format(pcm_oss_file);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SNDCTL_DSP_CHANNELS:
- if (get_user(res, p))
- return -EFAULT;
- res = snd_pcm_oss_set_channels(pcm_oss_file, res);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SOUND_PCM_READ_CHANNELS:
- res = snd_pcm_oss_get_channels(pcm_oss_file);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SOUND_PCM_WRITE_FILTER:
- case SOUND_PCM_READ_FILTER:
- return -EIO;
- case SNDCTL_DSP_POST:
- return snd_pcm_oss_post(pcm_oss_file);
- case SNDCTL_DSP_SUBDIVIDE:
- if (get_user(res, p))
- return -EFAULT;
- res = snd_pcm_oss_set_subdivide(pcm_oss_file, res);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SNDCTL_DSP_SETFRAGMENT:
- if (get_user(res, p))
- return -EFAULT;
- return snd_pcm_oss_set_fragment(pcm_oss_file, res);
- case SNDCTL_DSP_GETFMTS:
- res = snd_pcm_oss_get_formats(pcm_oss_file);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SNDCTL_DSP_GETOSPACE:
- case SNDCTL_DSP_GETISPACE:
- return snd_pcm_oss_get_space(pcm_oss_file,
- cmd == SNDCTL_DSP_GETISPACE ?
- SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
- (struct audio_buf_info __user *) arg);
- case SNDCTL_DSP_NONBLOCK:
- return snd_pcm_oss_nonblock(file);
- case SNDCTL_DSP_GETCAPS:
- res = snd_pcm_oss_get_caps(pcm_oss_file);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SNDCTL_DSP_GETTRIGGER:
- res = snd_pcm_oss_get_trigger(pcm_oss_file);
- if (res < 0)
- return res;
- return put_user(res, p);
- case SNDCTL_DSP_SETTRIGGER:
- if (get_user(res, p))
- return -EFAULT;
- return snd_pcm_oss_set_trigger(pcm_oss_file, res);
- case SNDCTL_DSP_GETIPTR:
- case SNDCTL_DSP_GETOPTR:
- return snd_pcm_oss_get_ptr(pcm_oss_file,
- cmd == SNDCTL_DSP_GETIPTR ?
- SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
- (struct count_info __user *) arg);
- case SNDCTL_DSP_MAPINBUF:
- case SNDCTL_DSP_MAPOUTBUF:
- return snd_pcm_oss_get_mapbuf(pcm_oss_file,
- cmd == SNDCTL_DSP_MAPINBUF ?
- SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
- (struct buffmem_desc __user *) arg);
- case SNDCTL_DSP_SETSYNCRO:
- /* stop DMA now.. */
- return 0;
- case SNDCTL_DSP_SETDUPLEX:
- if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX)
- return 0;
- return -EIO;
- case SNDCTL_DSP_GETODELAY:
- res = snd_pcm_oss_get_odelay(pcm_oss_file);
- if (res < 0) {
- /* it's for sure, some broken apps don't check for error codes */
- put_user(0, p);
- return res;
- }
- return put_user(res, p);
- case SNDCTL_DSP_PROFILE:
- return 0; /* silently ignore */
- default:
- snd_printd("pcm_oss: unknown command = 0x%x\n", cmd);
- }
- return -EINVAL;
-}
-
-#ifdef CONFIG_COMPAT
-/* all compatible */
-#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl
-#else
-#define snd_pcm_oss_ioctl_compat NULL
-#endif
-
-static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
-{
- struct snd_pcm_oss_file *pcm_oss_file;
- struct snd_pcm_substream *substream;
-
- pcm_oss_file = file->private_data;
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
- if (substream == NULL)
- return -ENXIO;
- substream->f_flags = file->f_flags & O_NONBLOCK;
-#ifndef OSS_DEBUG
- return snd_pcm_oss_read1(substream, buf, count);
-#else
- {
- ssize_t res = snd_pcm_oss_read1(substream, buf, count);
- printk(KERN_DEBUG "pcm_oss: read %li bytes "
- "(returned %li bytes)\n", (long)count, (long)res);
- return res;
- }
-#endif
-}
-
-static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
-{
- struct snd_pcm_oss_file *pcm_oss_file;
- struct snd_pcm_substream *substream;
- long result;
-
- pcm_oss_file = file->private_data;
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- if (substream == NULL)
- return -ENXIO;
- substream->f_flags = file->f_flags & O_NONBLOCK;
- result = snd_pcm_oss_write1(substream, buf, count);
-#ifdef OSS_DEBUG
- printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n",
- (long)count, (long)result);
-#endif
- return result;
-}
-
-static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (atomic_read(&substream->mmap_count))
- return runtime->oss.prev_hw_ptr_period !=
- get_hw_ptr_period(runtime);
- else
- return snd_pcm_playback_avail(runtime) >=
- runtime->oss.period_frames;
-}
-
-static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (atomic_read(&substream->mmap_count))
- return runtime->oss.prev_hw_ptr_period !=
- get_hw_ptr_period(runtime);
- else
- return snd_pcm_capture_avail(runtime) >=
- runtime->oss.period_frames;
-}
-
-static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
-{
- struct snd_pcm_oss_file *pcm_oss_file;
- unsigned int mask;
- struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
-
- pcm_oss_file = file->private_data;
-
- psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
-
- mask = 0;
- if (psubstream != NULL) {
- struct snd_pcm_runtime *runtime = psubstream->runtime;
- poll_wait(file, &runtime->sleep, wait);
- snd_pcm_stream_lock_irq(psubstream);
- if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&
- (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
- snd_pcm_oss_playback_ready(psubstream)))
- mask |= POLLOUT | POLLWRNORM;
- snd_pcm_stream_unlock_irq(psubstream);
- }
- if (csubstream != NULL) {
- struct snd_pcm_runtime *runtime = csubstream->runtime;
- snd_pcm_state_t ostate;
- poll_wait(file, &runtime->sleep, wait);
- snd_pcm_stream_lock_irq(csubstream);
- if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING ||
- snd_pcm_oss_capture_ready(csubstream))
- mask |= POLLIN | POLLRDNORM;
- snd_pcm_stream_unlock_irq(csubstream);
- if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
- struct snd_pcm_oss_file ofile;
- memset(&ofile, 0, sizeof(ofile));
- ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
- runtime->oss.trigger = 0;
- snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
- }
- }
-
- return mask;
-}
-
-static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
-{
- struct snd_pcm_oss_file *pcm_oss_file;
- struct snd_pcm_substream *substream = NULL;
- struct snd_pcm_runtime *runtime;
- int err;
-
-#ifdef OSS_DEBUG
- printk(KERN_DEBUG "pcm_oss: mmap begin\n");
-#endif
- pcm_oss_file = file->private_data;
- switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
- case VM_READ | VM_WRITE:
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- if (substream)
- break;
- /* Fall through */
- case VM_READ:
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
- break;
- case VM_WRITE:
- substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
- break;
- default:
- return -EINVAL;
- }
- /* set VM_READ access as well to fix memset() routines that do
- reads before writes (to improve performance) */
- area->vm_flags |= VM_READ;
- if (substream == NULL)
- return -ENXIO;
- runtime = substream->runtime;
- if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID))
- return -EIO;
- if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED)
- runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
- else
- return -EIO;
-
- if (runtime->oss.params) {
- if ((err = snd_pcm_oss_change_params(substream)) < 0)
- return err;
- }
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
- if (runtime->oss.plugin_first != NULL)
- return -EIO;
-#endif
-
- if (area->vm_pgoff != 0)
- return -EINVAL;
-
- err = snd_pcm_mmap_data(substream, file, area);
- if (err < 0)
- return err;
- runtime->oss.mmap_bytes = area->vm_end - area->vm_start;
- runtime->silence_threshold = 0;
- runtime->silence_size = 0;
-#ifdef OSS_DEBUG
- printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n",
- runtime->oss.mmap_bytes);
-#endif
- /* In mmap mode we never stop */
- runtime->stop_threshold = runtime->boundary;
-
- return 0;
-}
-
-#ifdef CONFIG_SND_VERBOSE_PROCFS
-/*
- * /proc interface
- */
-
-static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_str *pstr = entry->private_data;
- struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
- mutex_lock(&pstr->oss.setup_mutex);
- while (setup) {
- snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
- setup->task_name,
- setup->periods,
- setup->period_size,
- setup->disable ? " disable" : "",
- setup->direct ? " direct" : "",
- setup->block ? " block" : "",
- setup->nonblock ? " non-block" : "",
- setup->partialfrag ? " partial-frag" : "",
- setup->nosilence ? " no-silence" : "");
- setup = setup->next;
- }
- mutex_unlock(&pstr->oss.setup_mutex);
-}
-
-static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
-{
- struct snd_pcm_oss_setup *setup, *setupn;
-
- for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
- setup; setup = setupn) {
- setupn = setup->next;
- kfree(setup->task_name);
- kfree(setup);
- }
- pstr->oss.setup_list = NULL;
-}
-
-static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_str *pstr = entry->private_data;
- char line[128], str[32], task_name[32];
- const char *ptr;
- int idx1;
- struct snd_pcm_oss_setup *setup, *setup1, template;
-
- while (!snd_info_get_line(buffer, line, sizeof(line))) {
- mutex_lock(&pstr->oss.setup_mutex);
- memset(&template, 0, sizeof(template));
- ptr = snd_info_get_str(task_name, line, sizeof(task_name));
- if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {
- snd_pcm_oss_proc_free_setup_list(pstr);
- mutex_unlock(&pstr->oss.setup_mutex);
- continue;
- }
- for (setup = pstr->oss.setup_list; setup; setup = setup->next) {
- if (!strcmp(setup->task_name, task_name)) {
- template = *setup;
- break;
- }
- }
- ptr = snd_info_get_str(str, ptr, sizeof(str));
- template.periods = simple_strtoul(str, NULL, 10);
- ptr = snd_info_get_str(str, ptr, sizeof(str));
- template.period_size = simple_strtoul(str, NULL, 10);
- for (idx1 = 31; idx1 >= 0; idx1--)
- if (template.period_size & (1 << idx1))
- break;
- for (idx1--; idx1 >= 0; idx1--)
- template.period_size &= ~(1 << idx1);
- do {
- ptr = snd_info_get_str(str, ptr, sizeof(str));
- if (!strcmp(str, "disable")) {
- template.disable = 1;
- } else if (!strcmp(str, "direct")) {
- template.direct = 1;
- } else if (!strcmp(str, "block")) {
- template.block = 1;
- } else if (!strcmp(str, "non-block")) {
- template.nonblock = 1;
- } else if (!strcmp(str, "partial-frag")) {
- template.partialfrag = 1;
- } else if (!strcmp(str, "no-silence")) {
- template.nosilence = 1;
- } else if (!strcmp(str, "buggy-ptr")) {
- template.buggyptr = 1;
- }
- } while (*str);
- if (setup == NULL) {
- setup = kmalloc(sizeof(*setup), GFP_KERNEL);
- if (! setup) {
- buffer->error = -ENOMEM;
- mutex_unlock(&pstr->oss.setup_mutex);
- return;
- }
- if (pstr->oss.setup_list == NULL)
- pstr->oss.setup_list = setup;
- else {
- for (setup1 = pstr->oss.setup_list;
- setup1->next; setup1 = setup1->next);
- setup1->next = setup;
- }
- template.task_name = kstrdup(task_name, GFP_KERNEL);
- if (! template.task_name) {
- kfree(setup);
- buffer->error = -ENOMEM;
- mutex_unlock(&pstr->oss.setup_mutex);
- return;
- }
- }
- *setup = template;
- mutex_unlock(&pstr->oss.setup_mutex);
- }
-}
-
-static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
-{
- int stream;
- for (stream = 0; stream < 2; ++stream) {
- struct snd_info_entry *entry;
- struct snd_pcm_str *pstr = &pcm->streams[stream];
- if (pstr->substream_count == 0)
- continue;
- if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
- entry->c.text.read = snd_pcm_oss_proc_read;
- entry->c.text.write = snd_pcm_oss_proc_write;
- entry->private_data = pstr;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- pstr->oss.proc_entry = entry;
- }
-}
-
-static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
-{
- int stream;
- for (stream = 0; stream < 2; ++stream) {
- struct snd_pcm_str *pstr = &pcm->streams[stream];
- snd_info_free_entry(pstr->oss.proc_entry);
- pstr->oss.proc_entry = NULL;
- snd_pcm_oss_proc_free_setup_list(pstr);
- }
-}
-#else /* !CONFIG_SND_VERBOSE_PROCFS */
-#define snd_pcm_oss_proc_init(pcm)
-#define snd_pcm_oss_proc_done(pcm)
-#endif /* CONFIG_SND_VERBOSE_PROCFS */
-
-/*
- * ENTRY functions
- */
-
-static const struct file_operations snd_pcm_oss_f_reg =
-{
- .owner = THIS_MODULE,
- .read = snd_pcm_oss_read,
- .write = snd_pcm_oss_write,
- .open = snd_pcm_oss_open,
- .release = snd_pcm_oss_release,
- .llseek = no_llseek,
- .poll = snd_pcm_oss_poll,
- .unlocked_ioctl = snd_pcm_oss_ioctl,
- .compat_ioctl = snd_pcm_oss_ioctl_compat,
- .mmap = snd_pcm_oss_mmap,
-};
-
-static void register_oss_dsp(struct snd_pcm *pcm, int index)
-{
- char name[128];
- sprintf(name, "dsp%i%i", pcm->card->number, pcm->device);
- if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
- pcm->card, index, &snd_pcm_oss_f_reg,
- pcm, name) < 0) {
- snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n",
- pcm->card->number, pcm->device);
- }
-}
-
-static int snd_pcm_oss_register_minor(struct snd_pcm *pcm)
-{
- pcm->oss.reg = 0;
- if (dsp_map[pcm->card->number] == (int)pcm->device) {
- char name[128];
- int duplex;
- register_oss_dsp(pcm, 0);
- duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 &&
- pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count &&
- !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX));
- sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : "");
-#ifdef SNDRV_OSS_INFO_DEV_AUDIO
- snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO,
- pcm->card->number,
- name);
-#endif
- pcm->oss.reg++;
- pcm->oss.reg_mask |= 1;
- }
- if (adsp_map[pcm->card->number] == (int)pcm->device) {
- register_oss_dsp(pcm, 1);
- pcm->oss.reg++;
- pcm->oss.reg_mask |= 2;
- }
-
- if (pcm->oss.reg)
- snd_pcm_oss_proc_init(pcm);
-
- return 0;
-}
-
-static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm)
-{
- if (pcm->oss.reg) {
- if (pcm->oss.reg_mask & 1) {
- pcm->oss.reg_mask &= ~1;
- snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
- pcm->card, 0);
- }
- if (pcm->oss.reg_mask & 2) {
- pcm->oss.reg_mask &= ~2;
- snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
- pcm->card, 1);
- }
- if (dsp_map[pcm->card->number] == (int)pcm->device) {
-#ifdef SNDRV_OSS_INFO_DEV_AUDIO
- snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number);
-#endif
- }
- pcm->oss.reg = 0;
- }
- return 0;
-}
-
-static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm)
-{
- snd_pcm_oss_disconnect_minor(pcm);
- snd_pcm_oss_proc_done(pcm);
- return 0;
-}
-
-static struct snd_pcm_notify snd_pcm_oss_notify =
-{
- .n_register = snd_pcm_oss_register_minor,
- .n_disconnect = snd_pcm_oss_disconnect_minor,
- .n_unregister = snd_pcm_oss_unregister_minor,
-};
-
-static int __init alsa_pcm_oss_init(void)
-{
- int i;
- int err;
-
- /* check device map table */
- for (i = 0; i < SNDRV_CARDS; i++) {
- if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) {
- snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n",
- i, dsp_map[i]);
- dsp_map[i] = 0;
- }
- if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) {
- snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n",
- i, adsp_map[i]);
- adsp_map[i] = 1;
- }
- }
- if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0)
- return err;
- return 0;
-}
-
-static void __exit alsa_pcm_oss_exit(void)
-{
- snd_pcm_notify(&snd_pcm_oss_notify, 1);
-}
-
-module_init(alsa_pcm_oss_init)
-module_exit(alsa_pcm_oss_exit)
diff --git a/ANDROID_3.4.5/sound/core/oss/pcm_plugin.c b/ANDROID_3.4.5/sound/core/oss/pcm_plugin.c
deleted file mode 100644
index 71cc3ddf..00000000
--- a/ANDROID_3.4.5/sound/core/oss/pcm_plugin.c
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * PCM Plug-In shared (kernel/library) code
- * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
- * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#if 0
-#define PLUGIN_DEBUG
-#endif
-
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/vmalloc.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include "pcm_plugin.h"
-
-#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
-#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last)
-
-/*
- * because some cards might have rates "very close", we ignore
- * all "resampling" requests within +-5%
- */
-static int rate_match(unsigned int src_rate, unsigned int dst_rate)
-{
- unsigned int low = (src_rate * 95) / 100;
- unsigned int high = (src_rate * 105) / 100;
- return dst_rate >= low && dst_rate <= high;
-}
-
-static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
-{
- struct snd_pcm_plugin_format *format;
- ssize_t width;
- size_t size;
- unsigned int channel;
- struct snd_pcm_plugin_channel *c;
-
- if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- format = &plugin->src_format;
- } else {
- format = &plugin->dst_format;
- }
- if ((width = snd_pcm_format_physical_width(format->format)) < 0)
- return width;
- size = frames * format->channels * width;
- if (snd_BUG_ON(size % 8))
- return -ENXIO;
- size /= 8;
- if (plugin->buf_frames < frames) {
- vfree(plugin->buf);
- plugin->buf = vmalloc(size);
- plugin->buf_frames = frames;
- }
- if (!plugin->buf) {
- plugin->buf_frames = 0;
- return -ENOMEM;
- }
- c = plugin->buf_channels;
- if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
- for (channel = 0; channel < format->channels; channel++, c++) {
- c->frames = frames;
- c->enabled = 1;
- c->wanted = 0;
- c->area.addr = plugin->buf;
- c->area.first = channel * width;
- c->area.step = format->channels * width;
- }
- } else if (plugin->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
- if (snd_BUG_ON(size % format->channels))
- return -EINVAL;
- size /= format->channels;
- for (channel = 0; channel < format->channels; channel++, c++) {
- c->frames = frames;
- c->enabled = 1;
- c->wanted = 0;
- c->area.addr = plugin->buf + (channel * size);
- c->area.first = 0;
- c->area.step = width;
- }
- } else
- return -EINVAL;
- return 0;
-}
-
-int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames)
-{
- int err;
- if (snd_BUG_ON(!snd_pcm_plug_first(plug)))
- return -ENXIO;
- if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) {
- struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug);
- while (plugin->next) {
- if (plugin->dst_frames)
- frames = plugin->dst_frames(plugin, frames);
- if (snd_BUG_ON(frames <= 0))
- return -ENXIO;
- plugin = plugin->next;
- err = snd_pcm_plugin_alloc(plugin, frames);
- if (err < 0)
- return err;
- }
- } else {
- struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
- while (plugin->prev) {
- if (plugin->src_frames)
- frames = plugin->src_frames(plugin, frames);
- if (snd_BUG_ON(frames <= 0))
- return -ENXIO;
- plugin = plugin->prev;
- err = snd_pcm_plugin_alloc(plugin, frames);
- if (err < 0)
- return err;
- }
- }
- return 0;
-}
-
-
-snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin,
- snd_pcm_uframes_t frames,
- struct snd_pcm_plugin_channel **channels)
-{
- *channels = plugin->buf_channels;
- return frames;
-}
-
-int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
- const char *name,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- size_t extra,
- struct snd_pcm_plugin **ret)
-{
- struct snd_pcm_plugin *plugin;
- unsigned int channels;
-
- if (snd_BUG_ON(!plug))
- return -ENXIO;
- if (snd_BUG_ON(!src_format || !dst_format))
- return -ENXIO;
- plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL);
- if (plugin == NULL)
- return -ENOMEM;
- plugin->name = name;
- plugin->plug = plug;
- plugin->stream = snd_pcm_plug_stream(plug);
- plugin->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
- plugin->src_format = *src_format;
- plugin->src_width = snd_pcm_format_physical_width(src_format->format);
- snd_BUG_ON(plugin->src_width <= 0);
- plugin->dst_format = *dst_format;
- plugin->dst_width = snd_pcm_format_physical_width(dst_format->format);
- snd_BUG_ON(plugin->dst_width <= 0);
- if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK)
- channels = src_format->channels;
- else
- channels = dst_format->channels;
- plugin->buf_channels = kcalloc(channels, sizeof(*plugin->buf_channels), GFP_KERNEL);
- if (plugin->buf_channels == NULL) {
- snd_pcm_plugin_free(plugin);
- return -ENOMEM;
- }
- plugin->client_channels = snd_pcm_plugin_client_channels;
- *ret = plugin;
- return 0;
-}
-
-int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
-{
- if (! plugin)
- return 0;
- if (plugin->private_free)
- plugin->private_free(plugin);
- kfree(plugin->buf_channels);
- vfree(plugin->buf);
- kfree(plugin);
- return 0;
-}
-
-snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames)
-{
- struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
- int stream = snd_pcm_plug_stream(plug);
-
- if (snd_BUG_ON(!plug))
- return -ENXIO;
- if (drv_frames == 0)
- return 0;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- plugin = snd_pcm_plug_last(plug);
- while (plugin && drv_frames > 0) {
- plugin_prev = plugin->prev;
- if (plugin->src_frames)
- drv_frames = plugin->src_frames(plugin, drv_frames);
- plugin = plugin_prev;
- }
- } else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
- plugin = snd_pcm_plug_first(plug);
- while (plugin && drv_frames > 0) {
- plugin_next = plugin->next;
- if (plugin->dst_frames)
- drv_frames = plugin->dst_frames(plugin, drv_frames);
- plugin = plugin_next;
- }
- } else
- snd_BUG();
- return drv_frames;
-}
-
-snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t clt_frames)
-{
- struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
- snd_pcm_sframes_t frames;
- int stream = snd_pcm_plug_stream(plug);
-
- if (snd_BUG_ON(!plug))
- return -ENXIO;
- if (clt_frames == 0)
- return 0;
- frames = clt_frames;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- plugin = snd_pcm_plug_first(plug);
- while (plugin && frames > 0) {
- plugin_next = plugin->next;
- if (plugin->dst_frames) {
- frames = plugin->dst_frames(plugin, frames);
- if (frames < 0)
- return frames;
- }
- plugin = plugin_next;
- }
- } else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
- plugin = snd_pcm_plug_last(plug);
- while (plugin) {
- plugin_prev = plugin->prev;
- if (plugin->src_frames) {
- frames = plugin->src_frames(plugin, frames);
- if (frames < 0)
- return frames;
- }
- plugin = plugin_prev;
- }
- } else
- snd_BUG();
- return frames;
-}
-
-static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format)
-{
- struct snd_mask formats = *mask;
- u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
- SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
- SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE |
- SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_S24_3LE |
- SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE |
- SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
- SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
- snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW);
-
- if (formats.bits[0] & (u32)linfmts)
- formats.bits[0] |= (u32)linfmts;
- if (formats.bits[1] & (u32)(linfmts >> 32))
- formats.bits[1] |= (u32)(linfmts >> 32);
- return snd_mask_test(&formats, (__force int)format);
-}
-
-static snd_pcm_format_t preferred_formats[] = {
- SNDRV_PCM_FORMAT_S16_LE,
- SNDRV_PCM_FORMAT_S16_BE,
- SNDRV_PCM_FORMAT_U16_LE,
- SNDRV_PCM_FORMAT_U16_BE,
- SNDRV_PCM_FORMAT_S24_3LE,
- SNDRV_PCM_FORMAT_S24_3BE,
- SNDRV_PCM_FORMAT_U24_3LE,
- SNDRV_PCM_FORMAT_U24_3BE,
- SNDRV_PCM_FORMAT_S24_LE,
- SNDRV_PCM_FORMAT_S24_BE,
- SNDRV_PCM_FORMAT_U24_LE,
- SNDRV_PCM_FORMAT_U24_BE,
- SNDRV_PCM_FORMAT_S32_LE,
- SNDRV_PCM_FORMAT_S32_BE,
- SNDRV_PCM_FORMAT_U32_LE,
- SNDRV_PCM_FORMAT_U32_BE,
- SNDRV_PCM_FORMAT_S8,
- SNDRV_PCM_FORMAT_U8
-};
-
-snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
- struct snd_mask *format_mask)
-{
- int i;
-
- if (snd_mask_test(format_mask, (__force int)format))
- return format;
- if (!snd_pcm_plug_formats(format_mask, format))
- return (__force snd_pcm_format_t)-EINVAL;
- if (snd_pcm_format_linear(format)) {
- unsigned int width = snd_pcm_format_width(format);
- int unsignd = snd_pcm_format_unsigned(format) > 0;
- int big = snd_pcm_format_big_endian(format) > 0;
- unsigned int badness, best = -1;
- snd_pcm_format_t best_format = (__force snd_pcm_format_t)-1;
- for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) {
- snd_pcm_format_t f = preferred_formats[i];
- unsigned int w;
- if (!snd_mask_test(format_mask, (__force int)f))
- continue;
- w = snd_pcm_format_width(f);
- if (w >= width)
- badness = w - width;
- else
- badness = width - w + 32;
- badness += snd_pcm_format_unsigned(f) != unsignd;
- badness += snd_pcm_format_big_endian(f) != big;
- if (badness < best) {
- best_format = f;
- best = badness;
- }
- }
- if ((__force int)best_format >= 0)
- return best_format;
- else
- return (__force snd_pcm_format_t)-EINVAL;
- } else {
- switch (format) {
- case SNDRV_PCM_FORMAT_MU_LAW:
- for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
- snd_pcm_format_t format1 = preferred_formats[i];
- if (snd_mask_test(format_mask, (__force int)format1))
- return format1;
- }
- default:
- return (__force snd_pcm_format_t)-EINVAL;
- }
- }
-}
-
-int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
- struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_params *slave_params)
-{
- struct snd_pcm_plugin_format tmpformat;
- struct snd_pcm_plugin_format dstformat;
- struct snd_pcm_plugin_format srcformat;
- snd_pcm_access_t src_access, dst_access;
- struct snd_pcm_plugin *plugin = NULL;
- int err;
- int stream = snd_pcm_plug_stream(plug);
- int slave_interleaved = (params_channels(slave_params) == 1 ||
- params_access(slave_params) == SNDRV_PCM_ACCESS_RW_INTERLEAVED);
-
- switch (stream) {
- case SNDRV_PCM_STREAM_PLAYBACK:
- dstformat.format = params_format(slave_params);
- dstformat.rate = params_rate(slave_params);
- dstformat.channels = params_channels(slave_params);
- srcformat.format = params_format(params);
- srcformat.rate = params_rate(params);
- srcformat.channels = params_channels(params);
- src_access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
- dst_access = (slave_interleaved ? SNDRV_PCM_ACCESS_RW_INTERLEAVED :
- SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
- break;
- case SNDRV_PCM_STREAM_CAPTURE:
- dstformat.format = params_format(params);
- dstformat.rate = params_rate(params);
- dstformat.channels = params_channels(params);
- srcformat.format = params_format(slave_params);
- srcformat.rate = params_rate(slave_params);
- srcformat.channels = params_channels(slave_params);
- src_access = (slave_interleaved ? SNDRV_PCM_ACCESS_RW_INTERLEAVED :
- SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
- dst_access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
- break;
- default:
- snd_BUG();
- return -EINVAL;
- }
- tmpformat = srcformat;
-
- pdprintf("srcformat: format=%i, rate=%i, channels=%i\n",
- srcformat.format,
- srcformat.rate,
- srcformat.channels);
- pdprintf("dstformat: format=%i, rate=%i, channels=%i\n",
- dstformat.format,
- dstformat.rate,
- dstformat.channels);
-
- /* Format change (linearization) */
- if (! rate_match(srcformat.rate, dstformat.rate) &&
- ! snd_pcm_format_linear(srcformat.format)) {
- if (srcformat.format != SNDRV_PCM_FORMAT_MU_LAW)
- return -EINVAL;
- tmpformat.format = SNDRV_PCM_FORMAT_S16;
- err = snd_pcm_plugin_build_mulaw(plug,
- &srcformat, &tmpformat,
- &plugin);
- if (err < 0)
- return err;
- err = snd_pcm_plugin_append(plugin);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
- srcformat = tmpformat;
- src_access = dst_access;
- }
-
- /* channels reduction */
- if (srcformat.channels > dstformat.channels) {
- tmpformat.channels = dstformat.channels;
- err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);
- pdprintf("channels reduction: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
- if (err < 0)
- return err;
- err = snd_pcm_plugin_append(plugin);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
- srcformat = tmpformat;
- src_access = dst_access;
- }
-
- /* rate resampling */
- if (!rate_match(srcformat.rate, dstformat.rate)) {
- if (srcformat.format != SNDRV_PCM_FORMAT_S16) {
- /* convert to S16 for resampling */
- tmpformat.format = SNDRV_PCM_FORMAT_S16;
- err = snd_pcm_plugin_build_linear(plug,
- &srcformat, &tmpformat,
- &plugin);
- if (err < 0)
- return err;
- err = snd_pcm_plugin_append(plugin);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
- srcformat = tmpformat;
- src_access = dst_access;
- }
- tmpformat.rate = dstformat.rate;
- err = snd_pcm_plugin_build_rate(plug,
- &srcformat, &tmpformat,
- &plugin);
- pdprintf("rate down resampling: src=%i, dst=%i returns %i\n", srcformat.rate, tmpformat.rate, err);
- if (err < 0)
- return err;
- err = snd_pcm_plugin_append(plugin);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
- srcformat = tmpformat;
- src_access = dst_access;
- }
-
- /* format change */
- if (srcformat.format != dstformat.format) {
- tmpformat.format = dstformat.format;
- if (srcformat.format == SNDRV_PCM_FORMAT_MU_LAW ||
- tmpformat.format == SNDRV_PCM_FORMAT_MU_LAW) {
- err = snd_pcm_plugin_build_mulaw(plug,
- &srcformat, &tmpformat,
- &plugin);
- }
- else if (snd_pcm_format_linear(srcformat.format) &&
- snd_pcm_format_linear(tmpformat.format)) {
- err = snd_pcm_plugin_build_linear(plug,
- &srcformat, &tmpformat,
- &plugin);
- }
- else
- return -EINVAL;
- pdprintf("format change: src=%i, dst=%i returns %i\n", srcformat.format, tmpformat.format, err);
- if (err < 0)
- return err;
- err = snd_pcm_plugin_append(plugin);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
- srcformat = tmpformat;
- src_access = dst_access;
- }
-
- /* channels extension */
- if (srcformat.channels < dstformat.channels) {
- tmpformat.channels = dstformat.channels;
- err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);
- pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
- if (err < 0)
- return err;
- err = snd_pcm_plugin_append(plugin);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
- srcformat = tmpformat;
- src_access = dst_access;
- }
-
- /* de-interleave */
- if (src_access != dst_access) {
- err = snd_pcm_plugin_build_copy(plug,
- &srcformat,
- &tmpformat,
- &plugin);
- pdprintf("interleave change (copy: returns %i)\n", err);
- if (err < 0)
- return err;
- err = snd_pcm_plugin_append(plugin);
- if (err < 0) {
- snd_pcm_plugin_free(plugin);
- return err;
- }
- }
-
- return 0;
-}
-
-snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plug,
- char *buf,
- snd_pcm_uframes_t count,
- struct snd_pcm_plugin_channel **channels)
-{
- struct snd_pcm_plugin *plugin;
- struct snd_pcm_plugin_channel *v;
- struct snd_pcm_plugin_format *format;
- int width, nchannels, channel;
- int stream = snd_pcm_plug_stream(plug);
-
- if (snd_BUG_ON(!buf))
- return -ENXIO;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- plugin = snd_pcm_plug_first(plug);
- format = &plugin->src_format;
- } else {
- plugin = snd_pcm_plug_last(plug);
- format = &plugin->dst_format;
- }
- v = plugin->buf_channels;
- *channels = v;
- if ((width = snd_pcm_format_physical_width(format->format)) < 0)
- return width;
- nchannels = format->channels;
- if (snd_BUG_ON(plugin->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
- format->channels > 1))
- return -ENXIO;
- for (channel = 0; channel < nchannels; channel++, v++) {
- v->frames = count;
- v->enabled = 1;
- v->wanted = (stream == SNDRV_PCM_STREAM_CAPTURE);
- v->area.addr = buf;
- v->area.first = channel * width;
- v->area.step = nchannels * width;
- }
- return count;
-}
-
-snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *src_channels, snd_pcm_uframes_t size)
-{
- struct snd_pcm_plugin *plugin, *next;
- struct snd_pcm_plugin_channel *dst_channels;
- int err;
- snd_pcm_sframes_t frames = size;
-
- plugin = snd_pcm_plug_first(plug);
- while (plugin && frames > 0) {
- if ((next = plugin->next) != NULL) {
- snd_pcm_sframes_t frames1 = frames;
- if (plugin->dst_frames)
- frames1 = plugin->dst_frames(plugin, frames);
- if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) {
- return err;
- }
- if (err != frames1) {
- frames = err;
- if (plugin->src_frames)
- frames = plugin->src_frames(plugin, frames1);
- }
- } else
- dst_channels = NULL;
- pdprintf("write plugin: %s, %li\n", plugin->name, frames);
- if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)
- return frames;
- src_channels = dst_channels;
- plugin = next;
- }
- return snd_pcm_plug_client_size(plug, frames);
-}
-
-snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *dst_channels_final, snd_pcm_uframes_t size)
-{
- struct snd_pcm_plugin *plugin, *next;
- struct snd_pcm_plugin_channel *src_channels, *dst_channels;
- snd_pcm_sframes_t frames = size;
- int err;
-
- frames = snd_pcm_plug_slave_size(plug, frames);
- if (frames < 0)
- return frames;
-
- src_channels = NULL;
- plugin = snd_pcm_plug_first(plug);
- while (plugin && frames > 0) {
- if ((next = plugin->next) != NULL) {
- if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) {
- return err;
- }
- frames = err;
- } else {
- dst_channels = dst_channels_final;
- }
- pdprintf("read plugin: %s, %li\n", plugin->name, frames);
- if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)
- return frames;
- plugin = next;
- src_channels = dst_channels;
- }
- return frames;
-}
-
-int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
- size_t samples, snd_pcm_format_t format)
-{
- /* FIXME: sub byte resolution and odd dst_offset */
- unsigned char *dst;
- unsigned int dst_step;
- int width;
- const unsigned char *silence;
- if (!dst_area->addr)
- return 0;
- dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
- width = snd_pcm_format_physical_width(format);
- if (width <= 0)
- return -EINVAL;
- if (dst_area->step == (unsigned int) width && width >= 8)
- return snd_pcm_format_set_silence(format, dst, samples);
- silence = snd_pcm_format_silence_64(format);
- if (! silence)
- return -EINVAL;
- dst_step = dst_area->step / 8;
- if (width == 4) {
- /* Ima ADPCM */
- int dstbit = dst_area->first % 8;
- int dstbit_step = dst_area->step % 8;
- while (samples-- > 0) {
- if (dstbit)
- *dst &= 0xf0;
- else
- *dst &= 0x0f;
- dst += dst_step;
- dstbit += dstbit_step;
- if (dstbit == 8) {
- dst++;
- dstbit = 0;
- }
- }
- } else {
- width /= 8;
- while (samples-- > 0) {
- memcpy(dst, silence, width);
- dst += dst_step;
- }
- }
- return 0;
-}
-
-int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset,
- const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
- size_t samples, snd_pcm_format_t format)
-{
- /* FIXME: sub byte resolution and odd dst_offset */
- char *src, *dst;
- int width;
- int src_step, dst_step;
- src = src_area->addr + (src_area->first + src_area->step * src_offset) / 8;
- if (!src_area->addr)
- return snd_pcm_area_silence(dst_area, dst_offset, samples, format);
- dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
- if (!dst_area->addr)
- return 0;
- width = snd_pcm_format_physical_width(format);
- if (width <= 0)
- return -EINVAL;
- if (src_area->step == (unsigned int) width &&
- dst_area->step == (unsigned int) width && width >= 8) {
- size_t bytes = samples * width / 8;
- memcpy(dst, src, bytes);
- return 0;
- }
- src_step = src_area->step / 8;
- dst_step = dst_area->step / 8;
- if (width == 4) {
- /* Ima ADPCM */
- int srcbit = src_area->first % 8;
- int srcbit_step = src_area->step % 8;
- int dstbit = dst_area->first % 8;
- int dstbit_step = dst_area->step % 8;
- while (samples-- > 0) {
- unsigned char srcval;
- if (srcbit)
- srcval = *src & 0x0f;
- else
- srcval = (*src & 0xf0) >> 4;
- if (dstbit)
- *dst = (*dst & 0xf0) | srcval;
- else
- *dst = (*dst & 0x0f) | (srcval << 4);
- src += src_step;
- srcbit += srcbit_step;
- if (srcbit == 8) {
- src++;
- srcbit = 0;
- }
- dst += dst_step;
- dstbit += dstbit_step;
- if (dstbit == 8) {
- dst++;
- dstbit = 0;
- }
- }
- } else {
- width /= 8;
- while (samples-- > 0) {
- memcpy(dst, src, width);
- src += src_step;
- dst += dst_step;
- }
- }
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/oss/pcm_plugin.h b/ANDROID_3.4.5/sound/core/oss/pcm_plugin.h
deleted file mode 100644
index a5035c23..00000000
--- a/ANDROID_3.4.5/sound/core/oss/pcm_plugin.h
+++ /dev/null
@@ -1,185 +0,0 @@
-#ifndef __PCM_PLUGIN_H
-#define __PCM_PLUGIN_H
-
-/*
- * Digital Audio (Plugin interface) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-
-#define snd_pcm_plug_stream(plug) ((plug)->stream)
-
-enum snd_pcm_plugin_action {
- INIT = 0,
- PREPARE = 1,
-};
-
-struct snd_pcm_channel_area {
- void *addr; /* base address of channel samples */
- unsigned int first; /* offset to first sample in bits */
- unsigned int step; /* samples distance in bits */
-};
-
-struct snd_pcm_plugin_channel {
- void *aptr; /* pointer to the allocated area */
- struct snd_pcm_channel_area area;
- snd_pcm_uframes_t frames; /* allocated frames */
- unsigned int enabled:1; /* channel need to be processed */
- unsigned int wanted:1; /* channel is wanted */
-};
-
-struct snd_pcm_plugin_format {
- snd_pcm_format_t format;
- unsigned int rate;
- unsigned int channels;
-};
-
-struct snd_pcm_plugin {
- const char *name; /* plug-in name */
- int stream;
- struct snd_pcm_plugin_format src_format; /* source format */
- struct snd_pcm_plugin_format dst_format; /* destination format */
- int src_width; /* sample width in bits */
- int dst_width; /* sample width in bits */
- snd_pcm_access_t access;
- snd_pcm_sframes_t (*src_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t dst_frames);
- snd_pcm_sframes_t (*dst_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t src_frames);
- snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin,
- snd_pcm_uframes_t frames,
- struct snd_pcm_plugin_channel **channels);
- snd_pcm_sframes_t (*transfer)(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames);
- int (*action)(struct snd_pcm_plugin *plugin,
- enum snd_pcm_plugin_action action,
- unsigned long data);
- struct snd_pcm_plugin *prev;
- struct snd_pcm_plugin *next;
- struct snd_pcm_substream *plug;
- void *private_data;
- void (*private_free)(struct snd_pcm_plugin *plugin);
- char *buf;
- snd_pcm_uframes_t buf_frames;
- struct snd_pcm_plugin_channel *buf_channels;
- char extra_data[0];
-};
-
-int snd_pcm_plugin_build(struct snd_pcm_substream *handle,
- const char *name,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- size_t extra,
- struct snd_pcm_plugin **ret);
-int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin);
-int snd_pcm_plugin_clear(struct snd_pcm_plugin **first);
-int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames);
-snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size);
-snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size);
-
-#define FULL ROUTE_PLUGIN_RESOLUTION
-#define HALF ROUTE_PLUGIN_RESOLUTION / 2
-
-int snd_pcm_plugin_build_io(struct snd_pcm_substream *handle,
- struct snd_pcm_hw_params *params,
- struct snd_pcm_plugin **r_plugin);
-int snd_pcm_plugin_build_linear(struct snd_pcm_substream *handle,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin);
-int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *handle,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin);
-int snd_pcm_plugin_build_rate(struct snd_pcm_substream *handle,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin);
-int snd_pcm_plugin_build_route(struct snd_pcm_substream *handle,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin);
-int snd_pcm_plugin_build_copy(struct snd_pcm_substream *handle,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin);
-
-int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_params *slave_params);
-
-snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
- struct snd_mask *format_mask);
-
-int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin);
-
-snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *handle,
- struct snd_pcm_plugin_channel *src_channels,
- snd_pcm_uframes_t size);
-snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *handle,
- struct snd_pcm_plugin_channel *dst_channels_final,
- snd_pcm_uframes_t size);
-
-snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *handle,
- char *buf, snd_pcm_uframes_t count,
- struct snd_pcm_plugin_channel **channels);
-
-snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin,
- snd_pcm_uframes_t frames,
- struct snd_pcm_plugin_channel **channels);
-
-int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_channel,
- size_t dst_offset,
- size_t samples, snd_pcm_format_t format);
-int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel,
- size_t src_offset,
- const struct snd_pcm_channel_area *dst_channel,
- size_t dst_offset,
- size_t samples, snd_pcm_format_t format);
-
-void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size);
-void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr);
-snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream,
- const char *ptr, snd_pcm_uframes_t size,
- int in_kernel);
-snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream,
- char *ptr, snd_pcm_uframes_t size, int in_kernel);
-snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames,
- int in_kernel);
-snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames,
- int in_kernel);
-
-#else
-
-static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
-static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; }
-static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; }
-
-#endif
-
-#ifdef PLUGIN_DEBUG
-#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args)
-#else
-#define pdprintf(fmt, args...)
-#endif
-
-#endif /* __PCM_PLUGIN_H */
diff --git a/ANDROID_3.4.5/sound/core/oss/rate.c b/ANDROID_3.4.5/sound/core/oss/rate.c
deleted file mode 100644
index 2fa9299a..00000000
--- a/ANDROID_3.4.5/sound/core/oss/rate.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Rate conversion Plug-In
- * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/time.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include "pcm_plugin.h"
-
-#define SHIFT 11
-#define BITS (1<<SHIFT)
-#define R_MASK (BITS-1)
-
-/*
- * Basic rate conversion plugin
- */
-
-struct rate_channel {
- signed short last_S1;
- signed short last_S2;
-};
-
-typedef void (*rate_f)(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- int src_frames, int dst_frames);
-
-struct rate_priv {
- unsigned int pitch;
- unsigned int pos;
- rate_f func;
- snd_pcm_sframes_t old_src_frames, old_dst_frames;
- struct rate_channel channels[0];
-};
-
-static void rate_init(struct snd_pcm_plugin *plugin)
-{
- unsigned int channel;
- struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
- data->pos = 0;
- for (channel = 0; channel < plugin->src_format.channels; channel++) {
- data->channels[channel].last_S1 = 0;
- data->channels[channel].last_S2 = 0;
- }
-}
-
-static void resample_expand(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- int src_frames, int dst_frames)
-{
- unsigned int pos = 0;
- signed int val;
- signed short S1, S2;
- signed short *src, *dst;
- unsigned int channel;
- int src_step, dst_step;
- int src_frames1, dst_frames1;
- struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
- struct rate_channel *rchannels = data->channels;
-
- for (channel = 0; channel < plugin->src_format.channels; channel++) {
- pos = data->pos;
- S1 = rchannels->last_S1;
- S2 = rchannels->last_S2;
- if (!src_channels[channel].enabled) {
- if (dst_channels[channel].wanted)
- snd_pcm_area_silence(&dst_channels[channel].area, 0, dst_frames, plugin->dst_format.format);
- dst_channels[channel].enabled = 0;
- continue;
- }
- dst_channels[channel].enabled = 1;
- src = (signed short *)src_channels[channel].area.addr +
- src_channels[channel].area.first / 8 / 2;
- dst = (signed short *)dst_channels[channel].area.addr +
- dst_channels[channel].area.first / 8 / 2;
- src_step = src_channels[channel].area.step / 8 / 2;
- dst_step = dst_channels[channel].area.step / 8 / 2;
- src_frames1 = src_frames;
- dst_frames1 = dst_frames;
- while (dst_frames1-- > 0) {
- if (pos & ~R_MASK) {
- pos &= R_MASK;
- S1 = S2;
- if (src_frames1-- > 0) {
- S2 = *src;
- src += src_step;
- }
- }
- val = S1 + ((S2 - S1) * (signed int)pos) / BITS;
- if (val < -32768)
- val = -32768;
- else if (val > 32767)
- val = 32767;
- *dst = val;
- dst += dst_step;
- pos += data->pitch;
- }
- rchannels->last_S1 = S1;
- rchannels->last_S2 = S2;
- rchannels++;
- }
- data->pos = pos;
-}
-
-static void resample_shrink(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- int src_frames, int dst_frames)
-{
- unsigned int pos = 0;
- signed int val;
- signed short S1, S2;
- signed short *src, *dst;
- unsigned int channel;
- int src_step, dst_step;
- int src_frames1, dst_frames1;
- struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
- struct rate_channel *rchannels = data->channels;
-
- for (channel = 0; channel < plugin->src_format.channels; ++channel) {
- pos = data->pos;
- S1 = rchannels->last_S1;
- S2 = rchannels->last_S2;
- if (!src_channels[channel].enabled) {
- if (dst_channels[channel].wanted)
- snd_pcm_area_silence(&dst_channels[channel].area, 0, dst_frames, plugin->dst_format.format);
- dst_channels[channel].enabled = 0;
- continue;
- }
- dst_channels[channel].enabled = 1;
- src = (signed short *)src_channels[channel].area.addr +
- src_channels[channel].area.first / 8 / 2;
- dst = (signed short *)dst_channels[channel].area.addr +
- dst_channels[channel].area.first / 8 / 2;
- src_step = src_channels[channel].area.step / 8 / 2;
- dst_step = dst_channels[channel].area.step / 8 / 2;
- src_frames1 = src_frames;
- dst_frames1 = dst_frames;
- while (dst_frames1 > 0) {
- S1 = S2;
- if (src_frames1-- > 0) {
- S2 = *src;
- src += src_step;
- }
- if (pos & ~R_MASK) {
- pos &= R_MASK;
- val = S1 + ((S2 - S1) * (signed int)pos) / BITS;
- if (val < -32768)
- val = -32768;
- else if (val > 32767)
- val = 32767;
- *dst = val;
- dst += dst_step;
- dst_frames1--;
- }
- pos += data->pitch;
- }
- rchannels->last_S1 = S1;
- rchannels->last_S2 = S2;
- rchannels++;
- }
- data->pos = pos;
-}
-
-static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
-{
- struct rate_priv *data;
- snd_pcm_sframes_t res;
-
- if (snd_BUG_ON(!plugin))
- return -ENXIO;
- if (frames == 0)
- return 0;
- data = (struct rate_priv *)plugin->extra_data;
- if (plugin->src_format.rate < plugin->dst_format.rate) {
- res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
- } else {
- res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch);
- }
- if (data->old_src_frames > 0) {
- snd_pcm_sframes_t frames1 = frames, res1 = data->old_dst_frames;
- while (data->old_src_frames < frames1) {
- frames1 >>= 1;
- res1 <<= 1;
- }
- while (data->old_src_frames > frames1) {
- frames1 <<= 1;
- res1 >>= 1;
- }
- if (data->old_src_frames == frames1)
- return res1;
- }
- data->old_src_frames = frames;
- data->old_dst_frames = res;
- return res;
-}
-
-static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
-{
- struct rate_priv *data;
- snd_pcm_sframes_t res;
-
- if (snd_BUG_ON(!plugin))
- return -ENXIO;
- if (frames == 0)
- return 0;
- data = (struct rate_priv *)plugin->extra_data;
- if (plugin->src_format.rate < plugin->dst_format.rate) {
- res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch);
- } else {
- res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
- }
- if (data->old_dst_frames > 0) {
- snd_pcm_sframes_t frames1 = frames, res1 = data->old_src_frames;
- while (data->old_dst_frames < frames1) {
- frames1 >>= 1;
- res1 <<= 1;
- }
- while (data->old_dst_frames > frames1) {
- frames1 <<= 1;
- res1 >>= 1;
- }
- if (data->old_dst_frames == frames1)
- return res1;
- }
- data->old_dst_frames = frames;
- data->old_src_frames = res;
- return res;
-}
-
-static snd_pcm_sframes_t rate_transfer(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- snd_pcm_uframes_t dst_frames;
- struct rate_priv *data;
-
- if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
- return -ENXIO;
- if (frames == 0)
- return 0;
-#ifdef CONFIG_SND_DEBUG
- {
- unsigned int channel;
- for (channel = 0; channel < plugin->src_format.channels; channel++) {
- if (snd_BUG_ON(src_channels[channel].area.first % 8 ||
- src_channels[channel].area.step % 8))
- return -ENXIO;
- if (snd_BUG_ON(dst_channels[channel].area.first % 8 ||
- dst_channels[channel].area.step % 8))
- return -ENXIO;
- }
- }
-#endif
-
- dst_frames = rate_dst_frames(plugin, frames);
- if (dst_frames > dst_channels[0].frames)
- dst_frames = dst_channels[0].frames;
- data = (struct rate_priv *)plugin->extra_data;
- data->func(plugin, src_channels, dst_channels, frames, dst_frames);
- return dst_frames;
-}
-
-static int rate_action(struct snd_pcm_plugin *plugin,
- enum snd_pcm_plugin_action action,
- unsigned long udata)
-{
- if (snd_BUG_ON(!plugin))
- return -ENXIO;
- switch (action) {
- case INIT:
- case PREPARE:
- rate_init(plugin);
- break;
- default:
- break;
- }
- return 0; /* silenty ignore other actions */
-}
-
-int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin)
-{
- int err;
- struct rate_priv *data;
- struct snd_pcm_plugin *plugin;
-
- if (snd_BUG_ON(!r_plugin))
- return -ENXIO;
- *r_plugin = NULL;
-
- if (snd_BUG_ON(src_format->channels != dst_format->channels))
- return -ENXIO;
- if (snd_BUG_ON(src_format->channels <= 0))
- return -ENXIO;
- if (snd_BUG_ON(src_format->format != SNDRV_PCM_FORMAT_S16))
- return -ENXIO;
- if (snd_BUG_ON(dst_format->format != SNDRV_PCM_FORMAT_S16))
- return -ENXIO;
- if (snd_BUG_ON(src_format->rate == dst_format->rate))
- return -ENXIO;
-
- err = snd_pcm_plugin_build(plug, "rate conversion",
- src_format, dst_format,
- sizeof(struct rate_priv) +
- src_format->channels * sizeof(struct rate_channel),
- &plugin);
- if (err < 0)
- return err;
- data = (struct rate_priv *)plugin->extra_data;
- if (src_format->rate < dst_format->rate) {
- data->pitch = ((src_format->rate << SHIFT) + (dst_format->rate >> 1)) / dst_format->rate;
- data->func = resample_expand;
- } else {
- data->pitch = ((dst_format->rate << SHIFT) + (src_format->rate >> 1)) / src_format->rate;
- data->func = resample_shrink;
- }
- data->pos = 0;
- rate_init(plugin);
- data->old_src_frames = data->old_dst_frames = 0;
- plugin->transfer = rate_transfer;
- plugin->src_frames = rate_src_frames;
- plugin->dst_frames = rate_dst_frames;
- plugin->action = rate_action;
- *r_plugin = plugin;
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/oss/route.c b/ANDROID_3.4.5/sound/core/oss/route.c
deleted file mode 100644
index c8171f57..00000000
--- a/ANDROID_3.4.5/sound/core/oss/route.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Route Plug-In
- * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/time.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include "pcm_plugin.h"
-
-static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
- snd_pcm_uframes_t frames, snd_pcm_format_t format)
-{
- int dst = 0;
- for (; dst < ndsts; ++dst) {
- if (dvp->wanted)
- snd_pcm_area_silence(&dvp->area, 0, frames, format);
- dvp->enabled = 0;
- dvp++;
- }
-}
-
-static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel,
- struct snd_pcm_plugin_channel *dst_channel,
- snd_pcm_uframes_t frames, snd_pcm_format_t format)
-{
- dst_channel->enabled = 1;
- snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
-}
-
-static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
- const struct snd_pcm_plugin_channel *src_channels,
- struct snd_pcm_plugin_channel *dst_channels,
- snd_pcm_uframes_t frames)
-{
- int nsrcs, ndsts, dst;
- struct snd_pcm_plugin_channel *dvp;
- snd_pcm_format_t format;
-
- if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
- return -ENXIO;
- if (frames == 0)
- return 0;
-
- nsrcs = plugin->src_format.channels;
- ndsts = plugin->dst_format.channels;
-
- format = plugin->dst_format.format;
- dvp = dst_channels;
- if (nsrcs <= 1) {
- /* expand to all channels */
- for (dst = 0; dst < ndsts; ++dst) {
- copy_area(src_channels, dvp, frames, format);
- dvp++;
- }
- return frames;
- }
-
- for (dst = 0; dst < ndsts && dst < nsrcs; ++dst) {
- copy_area(src_channels, dvp, frames, format);
- dvp++;
- src_channels++;
- }
- if (dst < ndsts)
- zero_areas(dvp, ndsts - dst, frames, format);
- return frames;
-}
-
-int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug,
- struct snd_pcm_plugin_format *src_format,
- struct snd_pcm_plugin_format *dst_format,
- struct snd_pcm_plugin **r_plugin)
-{
- struct snd_pcm_plugin *plugin;
- int err;
-
- if (snd_BUG_ON(!r_plugin))
- return -ENXIO;
- *r_plugin = NULL;
- if (snd_BUG_ON(src_format->rate != dst_format->rate))
- return -ENXIO;
- if (snd_BUG_ON(src_format->format != dst_format->format))
- return -ENXIO;
-
- err = snd_pcm_plugin_build(plug, "route conversion",
- src_format, dst_format, 0, &plugin);
- if (err < 0)
- return err;
-
- plugin->transfer = route_transfer;
- *r_plugin = plugin;
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/pcm.c b/ANDROID_3.4.5/sound/core/pcm.c
deleted file mode 100644
index e30e1be3..00000000
--- a/ANDROID_3.4.5/sound/core/pcm.c
+++ /dev/null
@@ -1,1220 +0,0 @@
-/*
- * Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/time.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <sound/pcm.h>
-#include <sound/control.h>
-#include <sound/info.h>
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
-MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
-MODULE_LICENSE("GPL");
-
-static LIST_HEAD(snd_pcm_devices);
-static LIST_HEAD(snd_pcm_notify_list);
-static DEFINE_MUTEX(register_mutex);
-
-static int snd_pcm_free(struct snd_pcm *pcm);
-static int snd_pcm_dev_free(struct snd_device *device);
-static int snd_pcm_dev_register(struct snd_device *device);
-static int snd_pcm_dev_disconnect(struct snd_device *device);
-
-static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device)
-{
- struct snd_pcm *pcm;
-
- list_for_each_entry(pcm, &snd_pcm_devices, list) {
- if (pcm->card == card && pcm->device == device)
- return pcm;
- }
- return NULL;
-}
-
-static int snd_pcm_next(struct snd_card *card, int device)
-{
- struct snd_pcm *pcm;
-
- list_for_each_entry(pcm, &snd_pcm_devices, list) {
- if (pcm->card == card && pcm->device > device)
- return pcm->device;
- else if (pcm->card->number > card->number)
- return -1;
- }
- return -1;
-}
-
-static int snd_pcm_add(struct snd_pcm *newpcm)
-{
- struct snd_pcm *pcm;
-
- list_for_each_entry(pcm, &snd_pcm_devices, list) {
- if (pcm->card == newpcm->card && pcm->device == newpcm->device)
- return -EBUSY;
- if (pcm->card->number > newpcm->card->number ||
- (pcm->card == newpcm->card &&
- pcm->device > newpcm->device)) {
- list_add(&newpcm->list, pcm->list.prev);
- return 0;
- }
- }
- list_add_tail(&newpcm->list, &snd_pcm_devices);
- return 0;
-}
-
-static int snd_pcm_control_ioctl(struct snd_card *card,
- struct snd_ctl_file *control,
- unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
- {
- int device;
-
- if (get_user(device, (int __user *)arg))
- return -EFAULT;
- mutex_lock(&register_mutex);
- device = snd_pcm_next(card, device);
- mutex_unlock(&register_mutex);
- if (put_user(device, (int __user *)arg))
- return -EFAULT;
- return 0;
- }
- case SNDRV_CTL_IOCTL_PCM_INFO:
- {
- struct snd_pcm_info __user *info;
- unsigned int device, subdevice;
- int stream;
- struct snd_pcm *pcm;
- struct snd_pcm_str *pstr;
- struct snd_pcm_substream *substream;
- int err;
-
- info = (struct snd_pcm_info __user *)arg;
- if (get_user(device, &info->device))
- return -EFAULT;
- if (get_user(stream, &info->stream))
- return -EFAULT;
- if (stream < 0 || stream > 1)
- return -EINVAL;
- if (get_user(subdevice, &info->subdevice))
- return -EFAULT;
- mutex_lock(&register_mutex);
- pcm = snd_pcm_get(card, device);
- if (pcm == NULL) {
- err = -ENXIO;
- goto _error;
- }
- pstr = &pcm->streams[stream];
- if (pstr->substream_count == 0) {
- err = -ENOENT;
- goto _error;
- }
- if (subdevice >= pstr->substream_count) {
- err = -ENXIO;
- goto _error;
- }
- for (substream = pstr->substream; substream;
- substream = substream->next)
- if (substream->number == (int)subdevice)
- break;
- if (substream == NULL) {
- err = -ENXIO;
- goto _error;
- }
- err = snd_pcm_info_user(substream, info);
- _error:
- mutex_unlock(&register_mutex);
- return err;
- }
- case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
- {
- int val;
-
- if (get_user(val, (int __user *)arg))
- return -EFAULT;
- control->prefer_pcm_subdevice = val;
- return 0;
- }
- }
- return -ENOIOCTLCMD;
-}
-
-#define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v
-
-static char *snd_pcm_format_names[] = {
- FORMAT(S8),
- FORMAT(U8),
- FORMAT(S16_LE),
- FORMAT(S16_BE),
- FORMAT(U16_LE),
- FORMAT(U16_BE),
- FORMAT(S24_LE),
- FORMAT(S24_BE),
- FORMAT(U24_LE),
- FORMAT(U24_BE),
- FORMAT(S32_LE),
- FORMAT(S32_BE),
- FORMAT(U32_LE),
- FORMAT(U32_BE),
- FORMAT(FLOAT_LE),
- FORMAT(FLOAT_BE),
- FORMAT(FLOAT64_LE),
- FORMAT(FLOAT64_BE),
- FORMAT(IEC958_SUBFRAME_LE),
- FORMAT(IEC958_SUBFRAME_BE),
- FORMAT(MU_LAW),
- FORMAT(A_LAW),
- FORMAT(IMA_ADPCM),
- FORMAT(MPEG),
- FORMAT(GSM),
- FORMAT(SPECIAL),
- FORMAT(S24_3LE),
- FORMAT(S24_3BE),
- FORMAT(U24_3LE),
- FORMAT(U24_3BE),
- FORMAT(S20_3LE),
- FORMAT(S20_3BE),
- FORMAT(U20_3LE),
- FORMAT(U20_3BE),
- FORMAT(S18_3LE),
- FORMAT(S18_3BE),
- FORMAT(U18_3LE),
- FORMAT(U18_3BE),
- FORMAT(G723_24),
- FORMAT(G723_24_1B),
- FORMAT(G723_40),
- FORMAT(G723_40_1B),
-};
-
-const char *snd_pcm_format_name(snd_pcm_format_t format)
-{
- if ((__force unsigned int)format >= ARRAY_SIZE(snd_pcm_format_names))
- return "Unknown";
- return snd_pcm_format_names[(__force unsigned int)format];
-}
-EXPORT_SYMBOL_GPL(snd_pcm_format_name);
-
-#ifdef CONFIG_SND_VERBOSE_PROCFS
-
-#define STATE(v) [SNDRV_PCM_STATE_##v] = #v
-#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v
-#define READY(v) [SNDRV_PCM_READY_##v] = #v
-#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v
-#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v
-#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v
-#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v
-#define START(v) [SNDRV_PCM_START_##v] = #v
-#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v
-
-static char *snd_pcm_stream_names[] = {
- STREAM(PLAYBACK),
- STREAM(CAPTURE),
-};
-
-static char *snd_pcm_state_names[] = {
- STATE(OPEN),
- STATE(SETUP),
- STATE(PREPARED),
- STATE(RUNNING),
- STATE(XRUN),
- STATE(DRAINING),
- STATE(PAUSED),
- STATE(SUSPENDED),
-};
-
-static char *snd_pcm_access_names[] = {
- ACCESS(MMAP_INTERLEAVED),
- ACCESS(MMAP_NONINTERLEAVED),
- ACCESS(MMAP_COMPLEX),
- ACCESS(RW_INTERLEAVED),
- ACCESS(RW_NONINTERLEAVED),
-};
-
-static char *snd_pcm_subformat_names[] = {
- SUBFORMAT(STD),
-};
-
-static char *snd_pcm_tstamp_mode_names[] = {
- TSTAMP(NONE),
- TSTAMP(ENABLE),
-};
-
-static const char *snd_pcm_stream_name(int stream)
-{
- return snd_pcm_stream_names[stream];
-}
-
-static const char *snd_pcm_access_name(snd_pcm_access_t access)
-{
- return snd_pcm_access_names[(__force int)access];
-}
-
-static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
-{
- return snd_pcm_subformat_names[(__force int)subformat];
-}
-
-static const char *snd_pcm_tstamp_mode_name(int mode)
-{
- return snd_pcm_tstamp_mode_names[mode];
-}
-
-static const char *snd_pcm_state_name(snd_pcm_state_t state)
-{
- return snd_pcm_state_names[(__force int)state];
-}
-
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-#include <linux/soundcard.h>
-
-static const char *snd_pcm_oss_format_name(int format)
-{
- switch (format) {
- case AFMT_MU_LAW:
- return "MU_LAW";
- case AFMT_A_LAW:
- return "A_LAW";
- case AFMT_IMA_ADPCM:
- return "IMA_ADPCM";
- case AFMT_U8:
- return "U8";
- case AFMT_S16_LE:
- return "S16_LE";
- case AFMT_S16_BE:
- return "S16_BE";
- case AFMT_S8:
- return "S8";
- case AFMT_U16_LE:
- return "U16_LE";
- case AFMT_U16_BE:
- return "U16_BE";
- case AFMT_MPEG:
- return "MPEG";
- default:
- return "unknown";
- }
-}
-#endif
-
-static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_info *info;
- int err;
-
- if (! substream)
- return;
-
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info) {
- printk(KERN_DEBUG "snd_pcm_proc_info_read: cannot malloc\n");
- return;
- }
-
- err = snd_pcm_info(substream, info);
- if (err < 0) {
- snd_iprintf(buffer, "error %d\n", err);
- kfree(info);
- return;
- }
- snd_iprintf(buffer, "card: %d\n", info->card);
- snd_iprintf(buffer, "device: %d\n", info->device);
- snd_iprintf(buffer, "subdevice: %d\n", info->subdevice);
- snd_iprintf(buffer, "stream: %s\n", snd_pcm_stream_name(info->stream));
- snd_iprintf(buffer, "id: %s\n", info->id);
- snd_iprintf(buffer, "name: %s\n", info->name);
- snd_iprintf(buffer, "subname: %s\n", info->subname);
- snd_iprintf(buffer, "class: %d\n", info->dev_class);
- snd_iprintf(buffer, "subclass: %d\n", info->dev_subclass);
- snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count);
- snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail);
- kfree(info);
-}
-
-static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- snd_pcm_proc_info_read(((struct snd_pcm_str *)entry->private_data)->substream,
- buffer);
-}
-
-static void snd_pcm_substream_proc_info_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- snd_pcm_proc_info_read(entry->private_data, buffer);
-}
-
-static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_substream *substream = entry->private_data;
- struct snd_pcm_runtime *runtime;
-
- mutex_lock(&substream->pcm->open_mutex);
- runtime = substream->runtime;
- if (!runtime) {
- snd_iprintf(buffer, "closed\n");
- goto unlock;
- }
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
- snd_iprintf(buffer, "no setup\n");
- goto unlock;
- }
- snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
- snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format));
- snd_iprintf(buffer, "subformat: %s\n", snd_pcm_subformat_name(runtime->subformat));
- snd_iprintf(buffer, "channels: %u\n", runtime->channels);
- snd_iprintf(buffer, "rate: %u (%u/%u)\n", runtime->rate, runtime->rate_num, runtime->rate_den);
- snd_iprintf(buffer, "period_size: %lu\n", runtime->period_size);
- snd_iprintf(buffer, "buffer_size: %lu\n", runtime->buffer_size);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (substream->oss.oss) {
- snd_iprintf(buffer, "OSS format: %s\n", snd_pcm_oss_format_name(runtime->oss.format));
- snd_iprintf(buffer, "OSS channels: %u\n", runtime->oss.channels);
- snd_iprintf(buffer, "OSS rate: %u\n", runtime->oss.rate);
- snd_iprintf(buffer, "OSS period bytes: %lu\n", (unsigned long)runtime->oss.period_bytes);
- snd_iprintf(buffer, "OSS periods: %u\n", runtime->oss.periods);
- snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
- }
-#endif
- unlock:
- mutex_unlock(&substream->pcm->open_mutex);
-}
-
-static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_substream *substream = entry->private_data;
- struct snd_pcm_runtime *runtime;
-
- mutex_lock(&substream->pcm->open_mutex);
- runtime = substream->runtime;
- if (!runtime) {
- snd_iprintf(buffer, "closed\n");
- goto unlock;
- }
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
- snd_iprintf(buffer, "no setup\n");
- goto unlock;
- }
- snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
- snd_iprintf(buffer, "period_step: %u\n", runtime->period_step);
- snd_iprintf(buffer, "avail_min: %lu\n", runtime->control->avail_min);
- snd_iprintf(buffer, "start_threshold: %lu\n", runtime->start_threshold);
- snd_iprintf(buffer, "stop_threshold: %lu\n", runtime->stop_threshold);
- snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
- snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
- snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
- unlock:
- mutex_unlock(&substream->pcm->open_mutex);
-}
-
-static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_substream *substream = entry->private_data;
- struct snd_pcm_runtime *runtime;
- struct snd_pcm_status status;
- int err;
-
- mutex_lock(&substream->pcm->open_mutex);
- runtime = substream->runtime;
- if (!runtime) {
- snd_iprintf(buffer, "closed\n");
- goto unlock;
- }
- memset(&status, 0, sizeof(status));
- err = snd_pcm_status(substream, &status);
- if (err < 0) {
- snd_iprintf(buffer, "error %d\n", err);
- goto unlock;
- }
- snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
- snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid));
- snd_iprintf(buffer, "trigger_time: %ld.%09ld\n",
- status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec);
- snd_iprintf(buffer, "tstamp : %ld.%09ld\n",
- status.tstamp.tv_sec, status.tstamp.tv_nsec);
- snd_iprintf(buffer, "delay : %ld\n", status.delay);
- snd_iprintf(buffer, "avail : %ld\n", status.avail);
- snd_iprintf(buffer, "avail_max : %ld\n", status.avail_max);
- snd_iprintf(buffer, "-----\n");
- snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr);
- snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);
- unlock:
- mutex_unlock(&substream->pcm->open_mutex);
-}
-
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_str *pstr = entry->private_data;
- snd_iprintf(buffer, "%d\n", pstr->xrun_debug);
-}
-
-static void snd_pcm_xrun_debug_write(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_str *pstr = entry->private_data;
- char line[64];
- if (!snd_info_get_line(buffer, line, sizeof(line)))
- pstr->xrun_debug = simple_strtoul(line, NULL, 10);
-}
-#endif
-
-static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
-{
- struct snd_pcm *pcm = pstr->pcm;
- struct snd_info_entry *entry;
- char name[16];
-
- sprintf(name, "pcm%i%c", pcm->device,
- pstr->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
- if ((entry = snd_info_create_card_entry(pcm->card, name, pcm->card->proc_root)) == NULL)
- return -ENOMEM;
- entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
- pstr->proc_root = entry;
-
- if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) {
- snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- pstr->proc_info_entry = entry;
-
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
- pstr->proc_root)) != NULL) {
- entry->c.text.read = snd_pcm_xrun_debug_read;
- entry->c.text.write = snd_pcm_xrun_debug_write;
- entry->mode |= S_IWUSR;
- entry->private_data = pstr;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- pstr->proc_xrun_debug_entry = entry;
-#endif
- return 0;
-}
-
-static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr)
-{
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- snd_info_free_entry(pstr->proc_xrun_debug_entry);
- pstr->proc_xrun_debug_entry = NULL;
-#endif
- snd_info_free_entry(pstr->proc_info_entry);
- pstr->proc_info_entry = NULL;
- snd_info_free_entry(pstr->proc_root);
- pstr->proc_root = NULL;
- return 0;
-}
-
-static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
-{
- struct snd_info_entry *entry;
- struct snd_card *card;
- char name[16];
-
- card = substream->pcm->card;
-
- sprintf(name, "sub%i", substream->number);
- if ((entry = snd_info_create_card_entry(card, name, substream->pstr->proc_root)) == NULL)
- return -ENOMEM;
- entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
- substream->proc_root = entry;
-
- if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) {
- snd_info_set_text_ops(entry, substream,
- snd_pcm_substream_proc_info_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_info_entry = entry;
-
- if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) {
- snd_info_set_text_ops(entry, substream,
- snd_pcm_substream_proc_hw_params_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_hw_params_entry = entry;
-
- if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) {
- snd_info_set_text_ops(entry, substream,
- snd_pcm_substream_proc_sw_params_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_sw_params_entry = entry;
-
- if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) {
- snd_info_set_text_ops(entry, substream,
- snd_pcm_substream_proc_status_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_status_entry = entry;
-
- return 0;
-}
-
-static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
-{
- snd_info_free_entry(substream->proc_info_entry);
- substream->proc_info_entry = NULL;
- snd_info_free_entry(substream->proc_hw_params_entry);
- substream->proc_hw_params_entry = NULL;
- snd_info_free_entry(substream->proc_sw_params_entry);
- substream->proc_sw_params_entry = NULL;
- snd_info_free_entry(substream->proc_status_entry);
- substream->proc_status_entry = NULL;
- snd_info_free_entry(substream->proc_root);
- substream->proc_root = NULL;
- return 0;
-}
-#else /* !CONFIG_SND_VERBOSE_PROCFS */
-static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; }
-static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; }
-static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; }
-static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }
-#endif /* CONFIG_SND_VERBOSE_PROCFS */
-
-/**
- * snd_pcm_new_stream - create a new PCM stream
- * @pcm: the pcm instance
- * @stream: the stream direction, SNDRV_PCM_STREAM_XXX
- * @substream_count: the number of substreams
- *
- * Creates a new stream for the pcm.
- * The corresponding stream on the pcm must have been empty before
- * calling this, i.e. zero must be given to the argument of
- * snd_pcm_new().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
-{
- int idx, err;
- struct snd_pcm_str *pstr = &pcm->streams[stream];
- struct snd_pcm_substream *substream, *prev;
-
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- mutex_init(&pstr->oss.setup_mutex);
-#endif
- pstr->stream = stream;
- pstr->pcm = pcm;
- pstr->substream_count = substream_count;
- if (substream_count > 0 && !pcm->internal) {
- err = snd_pcm_stream_proc_init(pstr);
- if (err < 0) {
- snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
- return err;
- }
- }
- prev = NULL;
- for (idx = 0, prev = NULL; idx < substream_count; idx++) {
- substream = kzalloc(sizeof(*substream), GFP_KERNEL);
- if (substream == NULL) {
- snd_printk(KERN_ERR "Cannot allocate PCM substream\n");
- return -ENOMEM;
- }
- substream->pcm = pcm;
- substream->pstr = pstr;
- substream->number = idx;
- substream->stream = stream;
- sprintf(substream->name, "subdevice #%i", idx);
- substream->buffer_bytes_max = UINT_MAX;
- if (prev == NULL)
- pstr->substream = substream;
- else
- prev->next = substream;
-
- if (!pcm->internal) {
- err = snd_pcm_substream_proc_init(substream);
- if (err < 0) {
- snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
- if (prev == NULL)
- pstr->substream = NULL;
- else
- prev->next = NULL;
- kfree(substream);
- return err;
- }
- }
- substream->group = &substream->self_group;
- spin_lock_init(&substream->self_group.lock);
- INIT_LIST_HEAD(&substream->self_group.substreams);
- list_add_tail(&substream->link_list, &substream->self_group.substreams);
- atomic_set(&substream->mmap_count, 0);
- prev = substream;
- }
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_new_stream);
-
-static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
- int playback_count, int capture_count, bool internal,
- struct snd_pcm **rpcm)
-{
- struct snd_pcm *pcm;
- int err;
- static struct snd_device_ops ops = {
- .dev_free = snd_pcm_dev_free,
- .dev_register = snd_pcm_dev_register,
- .dev_disconnect = snd_pcm_dev_disconnect,
- };
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- if (rpcm)
- *rpcm = NULL;
- pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
- if (pcm == NULL) {
- snd_printk(KERN_ERR "Cannot allocate PCM\n");
- return -ENOMEM;
- }
- pcm->card = card;
- pcm->device = device;
- pcm->internal = internal;
- if (id)
- strlcpy(pcm->id, id, sizeof(pcm->id));
- if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
- snd_pcm_free(pcm);
- return err;
- }
- if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count)) < 0) {
- snd_pcm_free(pcm);
- return err;
- }
- mutex_init(&pcm->open_mutex);
- init_waitqueue_head(&pcm->open_wait);
- if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) {
- snd_pcm_free(pcm);
- return err;
- }
- if (rpcm)
- *rpcm = pcm;
- return 0;
-}
-
-/**
- * snd_pcm_new - create a new PCM instance
- * @card: the card instance
- * @id: the id string
- * @device: the device index (zero based)
- * @playback_count: the number of substreams for playback
- * @capture_count: the number of substreams for capture
- * @rpcm: the pointer to store the new pcm instance
- *
- * Creates a new PCM instance.
- *
- * The pcm operators have to be set afterwards to the new instance
- * via snd_pcm_set_ops().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_new(struct snd_card *card, const char *id, int device,
- int playback_count, int capture_count, struct snd_pcm **rpcm)
-{
- return _snd_pcm_new(card, id, device, playback_count, capture_count,
- false, rpcm);
-}
-EXPORT_SYMBOL(snd_pcm_new);
-
-/**
- * snd_pcm_new_internal - create a new internal PCM instance
- * @card: the card instance
- * @id: the id string
- * @device: the device index (zero based - shared with normal PCMs)
- * @playback_count: the number of substreams for playback
- * @capture_count: the number of substreams for capture
- * @rpcm: the pointer to store the new pcm instance
- *
- * Creates a new internal PCM instance with no userspace device or procfs
- * entries. This is used by ASoC Back End PCMs in order to create a PCM that
- * will only be used internally by kernel drivers. i.e. it cannot be opened
- * by userspace. It provides existing ASoC components drivers with a substream
- * and access to any private data.
- *
- * The pcm operators have to be set afterwards to the new instance
- * via snd_pcm_set_ops().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
- int playback_count, int capture_count,
- struct snd_pcm **rpcm)
-{
- return _snd_pcm_new(card, id, device, playback_count, capture_count,
- true, rpcm);
-}
-EXPORT_SYMBOL(snd_pcm_new_internal);
-
-static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
-{
- struct snd_pcm_substream *substream, *substream_next;
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- struct snd_pcm_oss_setup *setup, *setupn;
-#endif
- substream = pstr->substream;
- while (substream) {
- substream_next = substream->next;
- snd_pcm_timer_done(substream);
- snd_pcm_substream_proc_done(substream);
- kfree(substream);
- substream = substream_next;
- }
- snd_pcm_stream_proc_done(pstr);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- for (setup = pstr->oss.setup_list; setup; setup = setupn) {
- setupn = setup->next;
- kfree(setup->task_name);
- kfree(setup);
- }
-#endif
-}
-
-static int snd_pcm_free(struct snd_pcm *pcm)
-{
- struct snd_pcm_notify *notify;
-
- if (!pcm)
- return 0;
- list_for_each_entry(notify, &snd_pcm_notify_list, list) {
- notify->n_unregister(pcm);
- }
- if (pcm->private_free)
- pcm->private_free(pcm);
- snd_pcm_lib_preallocate_free_for_all(pcm);
- snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]);
- snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_CAPTURE]);
- kfree(pcm);
- return 0;
-}
-
-static int snd_pcm_dev_free(struct snd_device *device)
-{
- struct snd_pcm *pcm = device->device_data;
- return snd_pcm_free(pcm);
-}
-
-int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
- struct file *file,
- struct snd_pcm_substream **rsubstream)
-{
- struct snd_pcm_str * pstr;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- struct snd_ctl_file *kctl;
- struct snd_card *card;
- int prefer_subdevice = -1;
- size_t size;
-
- if (snd_BUG_ON(!pcm || !rsubstream))
- return -ENXIO;
- *rsubstream = NULL;
- pstr = &pcm->streams[stream];
- if (pstr->substream == NULL || pstr->substream_count == 0)
- return -ENODEV;
-
- card = pcm->card;
- read_lock(&card->ctl_files_rwlock);
- list_for_each_entry(kctl, &card->ctl_files, list) {
- if (kctl->pid == task_pid(current)) {
- prefer_subdevice = kctl->prefer_pcm_subdevice;
- if (prefer_subdevice != -1)
- break;
- }
- }
- read_unlock(&card->ctl_files_rwlock);
-
- switch (stream) {
- case SNDRV_PCM_STREAM_PLAYBACK:
- if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
- for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) {
- if (SUBSTREAM_BUSY(substream))
- return -EAGAIN;
- }
- }
- break;
- case SNDRV_PCM_STREAM_CAPTURE:
- if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
- for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) {
- if (SUBSTREAM_BUSY(substream))
- return -EAGAIN;
- }
- }
- break;
- default:
- return -EINVAL;
- }
-
- if (file->f_flags & O_APPEND) {
- if (prefer_subdevice < 0) {
- if (pstr->substream_count > 1)
- return -EINVAL; /* must be unique */
- substream = pstr->substream;
- } else {
- for (substream = pstr->substream; substream;
- substream = substream->next)
- if (substream->number == prefer_subdevice)
- break;
- }
- if (! substream)
- return -ENODEV;
- if (! SUBSTREAM_BUSY(substream))
- return -EBADFD;
- substream->ref_count++;
- *rsubstream = substream;
- return 0;
- }
-
- if (prefer_subdevice >= 0) {
- for (substream = pstr->substream; substream; substream = substream->next)
- if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice)
- goto __ok;
- }
- for (substream = pstr->substream; substream; substream = substream->next)
- if (!SUBSTREAM_BUSY(substream))
- break;
- __ok:
- if (substream == NULL)
- return -EAGAIN;
-
- runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
- if (runtime == NULL)
- return -ENOMEM;
-
- size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status));
- runtime->status = snd_malloc_pages(size, GFP_KERNEL);
- if (runtime->status == NULL) {
- kfree(runtime);
- return -ENOMEM;
- }
- memset((void*)runtime->status, 0, size);
-
- size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control));
- runtime->control = snd_malloc_pages(size, GFP_KERNEL);
- if (runtime->control == NULL) {
- snd_free_pages((void*)runtime->status,
- PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
- kfree(runtime);
- return -ENOMEM;
- }
- memset((void*)runtime->control, 0, size);
-
- init_waitqueue_head(&runtime->sleep);
- init_waitqueue_head(&runtime->tsleep);
-
- runtime->status->state = SNDRV_PCM_STATE_OPEN;
-
- substream->runtime = runtime;
- substream->private_data = pcm->private_data;
- substream->ref_count = 1;
- substream->f_flags = file->f_flags;
- substream->pid = get_pid(task_pid(current));
- pstr->substream_opened++;
- *rsubstream = substream;
- return 0;
-}
-
-void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
-
- if (PCM_RUNTIME_CHECK(substream))
- return;
- runtime = substream->runtime;
- if (runtime->private_free != NULL)
- runtime->private_free(runtime);
- snd_free_pages((void*)runtime->status,
- PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
- snd_free_pages((void*)runtime->control,
- PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
- kfree(runtime->hw_constraints.rules);
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- if (runtime->hwptr_log)
- kfree(runtime->hwptr_log);
-#endif
- kfree(runtime);
- substream->runtime = NULL;
- put_pid(substream->pid);
- substream->pid = NULL;
- substream->pstr->substream_opened--;
-}
-
-static ssize_t show_pcm_class(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct snd_pcm *pcm;
- const char *str;
- static const char *strs[SNDRV_PCM_CLASS_LAST + 1] = {
- [SNDRV_PCM_CLASS_GENERIC] = "generic",
- [SNDRV_PCM_CLASS_MULTI] = "multi",
- [SNDRV_PCM_CLASS_MODEM] = "modem",
- [SNDRV_PCM_CLASS_DIGITIZER] = "digitizer",
- };
-
- if (! (pcm = dev_get_drvdata(dev)) ||
- pcm->dev_class > SNDRV_PCM_CLASS_LAST)
- str = "none";
- else
- str = strs[pcm->dev_class];
- return snprintf(buf, PAGE_SIZE, "%s\n", str);
-}
-
-static struct device_attribute pcm_attrs =
- __ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
-
-static int snd_pcm_dev_register(struct snd_device *device)
-{
- int cidx, err;
- struct snd_pcm_substream *substream;
- struct snd_pcm_notify *notify;
- char str[16];
- struct snd_pcm *pcm;
- struct device *dev;
-
- if (snd_BUG_ON(!device || !device->device_data))
- return -ENXIO;
- pcm = device->device_data;
- mutex_lock(&register_mutex);
- err = snd_pcm_add(pcm);
- if (err) {
- mutex_unlock(&register_mutex);
- return err;
- }
- for (cidx = 0; cidx < 2; cidx++) {
- int devtype = -1;
- if (pcm->streams[cidx].substream == NULL || pcm->internal)
- continue;
- switch (cidx) {
- case SNDRV_PCM_STREAM_PLAYBACK:
- sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);
- devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
- break;
- case SNDRV_PCM_STREAM_CAPTURE:
- sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);
- devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
- break;
- }
- /* device pointer to use, pcm->dev takes precedence if
- * it is assigned, otherwise fall back to card's device
- * if possible */
- dev = pcm->dev;
- if (!dev)
- dev = snd_card_get_device_link(pcm->card);
- /* register pcm */
- err = snd_register_device_for_dev(devtype, pcm->card,
- pcm->device,
- &snd_pcm_f_ops[cidx],
- pcm, str, dev);
- if (err < 0) {
- list_del(&pcm->list);
- mutex_unlock(&register_mutex);
- return err;
- }
- snd_add_device_sysfs_file(devtype, pcm->card, pcm->device,
- &pcm_attrs);
- for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
- snd_pcm_timer_init(substream);
- }
-
- list_for_each_entry(notify, &snd_pcm_notify_list, list)
- notify->n_register(pcm);
-
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-static int snd_pcm_dev_disconnect(struct snd_device *device)
-{
- struct snd_pcm *pcm = device->device_data;
- struct snd_pcm_notify *notify;
- struct snd_pcm_substream *substream;
- int cidx, devtype;
-
- mutex_lock(&register_mutex);
- if (list_empty(&pcm->list))
- goto unlock;
-
- mutex_lock(&pcm->open_mutex);
- wake_up(&pcm->open_wait);
- list_del_init(&pcm->list);
- for (cidx = 0; cidx < 2; cidx++)
- for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
- snd_pcm_stream_lock_irq(substream);
- if (substream->runtime) {
- substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
- wake_up(&substream->runtime->sleep);
- wake_up(&substream->runtime->tsleep);
- }
- snd_pcm_stream_unlock_irq(substream);
- }
- list_for_each_entry(notify, &snd_pcm_notify_list, list) {
- notify->n_disconnect(pcm);
- }
- for (cidx = 0; cidx < 2; cidx++) {
- devtype = -1;
- switch (cidx) {
- case SNDRV_PCM_STREAM_PLAYBACK:
- devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
- break;
- case SNDRV_PCM_STREAM_CAPTURE:
- devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
- break;
- }
- snd_unregister_device(devtype, pcm->card, pcm->device);
- }
- mutex_unlock(&pcm->open_mutex);
- unlock:
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
-{
- struct snd_pcm *pcm;
-
- if (snd_BUG_ON(!notify ||
- !notify->n_register ||
- !notify->n_unregister ||
- !notify->n_disconnect))
- return -EINVAL;
- mutex_lock(&register_mutex);
- if (nfree) {
- list_del(&notify->list);
- list_for_each_entry(pcm, &snd_pcm_devices, list)
- notify->n_unregister(pcm);
- } else {
- list_add_tail(&notify->list, &snd_pcm_notify_list);
- list_for_each_entry(pcm, &snd_pcm_devices, list)
- notify->n_register(pcm);
- }
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_notify);
-
-#ifdef CONFIG_PROC_FS
-/*
- * Info interface
- */
-
-static void snd_pcm_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm *pcm;
-
- mutex_lock(&register_mutex);
- list_for_each_entry(pcm, &snd_pcm_devices, list) {
- snd_iprintf(buffer, "%02i-%02i: %s : %s",
- pcm->card->number, pcm->device, pcm->id, pcm->name);
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
- snd_iprintf(buffer, " : playback %i",
- pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count);
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
- snd_iprintf(buffer, " : capture %i",
- pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count);
- snd_iprintf(buffer, "\n");
- }
- mutex_unlock(&register_mutex);
-}
-
-static struct snd_info_entry *snd_pcm_proc_entry;
-
-static void snd_pcm_proc_init(void)
-{
- struct snd_info_entry *entry;
-
- if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
- snd_info_set_text_ops(entry, NULL, snd_pcm_proc_read);
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- snd_pcm_proc_entry = entry;
-}
-
-static void snd_pcm_proc_done(void)
-{
- snd_info_free_entry(snd_pcm_proc_entry);
-}
-
-#else /* !CONFIG_PROC_FS */
-#define snd_pcm_proc_init()
-#define snd_pcm_proc_done()
-#endif /* CONFIG_PROC_FS */
-
-
-/*
- * ENTRY functions
- */
-
-static int __init alsa_pcm_init(void)
-{
- snd_ctl_register_ioctl(snd_pcm_control_ioctl);
- snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl);
- snd_pcm_proc_init();
- return 0;
-}
-
-static void __exit alsa_pcm_exit(void)
-{
- snd_ctl_unregister_ioctl(snd_pcm_control_ioctl);
- snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl);
- snd_pcm_proc_done();
-}
-
-module_init(alsa_pcm_init)
-module_exit(alsa_pcm_exit)
diff --git a/ANDROID_3.4.5/sound/core/pcm_compat.c b/ANDROID_3.4.5/sound/core/pcm_compat.c
deleted file mode 100644
index 91cdf943..00000000
--- a/ANDROID_3.4.5/sound/core/pcm_compat.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for PCM API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/* This file included from pcm_native.c */
-
-#include <linux/compat.h>
-#include <linux/slab.h>
-
-static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
- s32 __user *src)
-{
- snd_pcm_sframes_t delay;
- mm_segment_t fs;
- int err;
-
- fs = snd_enter_user();
- err = snd_pcm_delay(substream, &delay);
- snd_leave_user(fs);
- if (err < 0)
- return err;
- if (put_user(delay, src))
- return -EFAULT;
- return err;
-}
-
-static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
- u32 __user *src)
-{
- snd_pcm_uframes_t frames;
- int err;
-
- if (get_user(frames, src))
- return -EFAULT;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- err = snd_pcm_playback_rewind(substream, frames);
- else
- err = snd_pcm_capture_rewind(substream, frames);
- if (put_user(err, src))
- return -EFAULT;
- return err < 0 ? err : 0;
-}
-
-static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream,
- u32 __user *src)
-{
- snd_pcm_uframes_t frames;
- int err;
-
- if (get_user(frames, src))
- return -EFAULT;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- err = snd_pcm_playback_forward(substream, frames);
- else
- err = snd_pcm_capture_forward(substream, frames);
- if (put_user(err, src))
- return -EFAULT;
- return err < 0 ? err : 0;
-}
-
-struct snd_pcm_hw_params32 {
- u32 flags;
- struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */
- struct snd_mask mres[5]; /* reserved masks */
- struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
- struct snd_interval ires[9]; /* reserved intervals */
- u32 rmask;
- u32 cmask;
- u32 info;
- u32 msbits;
- u32 rate_num;
- u32 rate_den;
- u32 fifo_size;
- unsigned char reserved[64];
-};
-
-struct snd_pcm_sw_params32 {
- s32 tstamp_mode;
- u32 period_step;
- u32 sleep_min;
- u32 avail_min;
- u32 xfer_align;
- u32 start_threshold;
- u32 stop_threshold;
- u32 silence_threshold;
- u32 silence_size;
- u32 boundary;
- unsigned char reserved[64];
-};
-
-/* recalcuate the boundary within 32bit */
-static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
-{
- snd_pcm_uframes_t boundary;
-
- if (! runtime->buffer_size)
- return 0;
- boundary = runtime->buffer_size;
- while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
- boundary *= 2;
- return boundary;
-}
-
-static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream,
- struct snd_pcm_sw_params32 __user *src)
-{
- struct snd_pcm_sw_params params;
- snd_pcm_uframes_t boundary;
- int err;
-
- memset(&params, 0, sizeof(params));
- if (get_user(params.tstamp_mode, &src->tstamp_mode) ||
- get_user(params.period_step, &src->period_step) ||
- get_user(params.sleep_min, &src->sleep_min) ||
- get_user(params.avail_min, &src->avail_min) ||
- get_user(params.xfer_align, &src->xfer_align) ||
- get_user(params.start_threshold, &src->start_threshold) ||
- get_user(params.stop_threshold, &src->stop_threshold) ||
- get_user(params.silence_threshold, &src->silence_threshold) ||
- get_user(params.silence_size, &src->silence_size))
- return -EFAULT;
- /*
- * Check silent_size parameter. Since we have 64bit boundary,
- * silence_size must be compared with the 32bit boundary.
- */
- boundary = recalculate_boundary(substream->runtime);
- if (boundary && params.silence_size >= boundary)
- params.silence_size = substream->runtime->boundary;
- err = snd_pcm_sw_params(substream, &params);
- if (err < 0)
- return err;
- if (boundary && put_user(boundary, &src->boundary))
- return -EFAULT;
- return err;
-}
-
-struct snd_pcm_channel_info32 {
- u32 channel;
- u32 offset;
- u32 first;
- u32 step;
-};
-
-static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream,
- struct snd_pcm_channel_info32 __user *src)
-{
- struct snd_pcm_channel_info info;
- int err;
-
- if (get_user(info.channel, &src->channel) ||
- get_user(info.offset, &src->offset) ||
- get_user(info.first, &src->first) ||
- get_user(info.step, &src->step))
- return -EFAULT;
- err = snd_pcm_channel_info(substream, &info);
- if (err < 0)
- return err;
- if (put_user(info.channel, &src->channel) ||
- put_user(info.offset, &src->offset) ||
- put_user(info.first, &src->first) ||
- put_user(info.step, &src->step))
- return -EFAULT;
- return err;
-}
-
-struct snd_pcm_status32 {
- s32 state;
- struct compat_timespec trigger_tstamp;
- struct compat_timespec tstamp;
- u32 appl_ptr;
- u32 hw_ptr;
- s32 delay;
- u32 avail;
- u32 avail_max;
- u32 overrange;
- s32 suspended_state;
- unsigned char reserved[60];
-} __attribute__((packed));
-
-
-static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
- struct snd_pcm_status32 __user *src)
-{
- struct snd_pcm_status status;
- int err;
-
- err = snd_pcm_status(substream, &status);
- if (err < 0)
- return err;
-
- if (put_user(status.state, &src->state) ||
- put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) ||
- put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) ||
- put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
- put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
- put_user(status.appl_ptr, &src->appl_ptr) ||
- put_user(status.hw_ptr, &src->hw_ptr) ||
- put_user(status.delay, &src->delay) ||
- put_user(status.avail, &src->avail) ||
- put_user(status.avail_max, &src->avail_max) ||
- put_user(status.overrange, &src->overrange) ||
- put_user(status.suspended_state, &src->suspended_state))
- return -EFAULT;
-
- return err;
-}
-
-/* both for HW_PARAMS and HW_REFINE */
-static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
- int refine,
- struct snd_pcm_hw_params32 __user *data32)
-{
- struct snd_pcm_hw_params *data;
- struct snd_pcm_runtime *runtime;
- int err;
-
- if (! (runtime = substream->runtime))
- return -ENOTTY;
-
- /* only fifo_size is different, so just copy all */
- data = memdup_user(data32, sizeof(*data32));
- if (IS_ERR(data))
- return PTR_ERR(data);
-
- if (refine)
- err = snd_pcm_hw_refine(substream, data);
- else
- err = snd_pcm_hw_params(substream, data);
- if (err < 0)
- goto error;
- if (copy_to_user(data32, data, sizeof(*data32)) ||
- put_user(data->fifo_size, &data32->fifo_size)) {
- err = -EFAULT;
- goto error;
- }
-
- if (! refine) {
- unsigned int new_boundary = recalculate_boundary(runtime);
- if (new_boundary)
- runtime->boundary = new_boundary;
- }
- error:
- kfree(data);
- return err;
-}
-
-
-/*
- */
-struct snd_xferi32 {
- s32 result;
- u32 buf;
- u32 frames;
-};
-
-static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream,
- int dir, struct snd_xferi32 __user *data32)
-{
- compat_caddr_t buf;
- u32 frames;
- int err;
-
- if (! substream->runtime)
- return -ENOTTY;
- if (substream->stream != dir)
- return -EINVAL;
- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
-
- if (get_user(buf, &data32->buf) ||
- get_user(frames, &data32->frames))
- return -EFAULT;
-
- if (dir == SNDRV_PCM_STREAM_PLAYBACK)
- err = snd_pcm_lib_write(substream, compat_ptr(buf), frames);
- else
- err = snd_pcm_lib_read(substream, compat_ptr(buf), frames);
- if (err < 0)
- return err;
- /* copy the result */
- if (put_user(err, &data32->result))
- return -EFAULT;
- return 0;
-}
-
-
-/* snd_xfern needs remapping of bufs */
-struct snd_xfern32 {
- s32 result;
- u32 bufs; /* this is void **; */
- u32 frames;
-};
-
-/*
- * xfern ioctl nees to copy (up to) 128 pointers on stack.
- * although we may pass the copied pointers through f_op->ioctl, but the ioctl
- * handler there expands again the same 128 pointers on stack, so it is better
- * to handle the function (calling pcm_readv/writev) directly in this handler.
- */
-static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
- int dir, struct snd_xfern32 __user *data32)
-{
- compat_caddr_t buf;
- compat_caddr_t __user *bufptr;
- u32 frames;
- void __user **bufs;
- int err, ch, i;
-
- if (! substream->runtime)
- return -ENOTTY;
- if (substream->stream != dir)
- return -EINVAL;
-
- if ((ch = substream->runtime->channels) > 128)
- return -EINVAL;
- if (get_user(buf, &data32->bufs) ||
- get_user(frames, &data32->frames))
- return -EFAULT;
- bufptr = compat_ptr(buf);
- bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL);
- if (bufs == NULL)
- return -ENOMEM;
- for (i = 0; i < ch; i++) {
- u32 ptr;
- if (get_user(ptr, bufptr)) {
- kfree(bufs);
- return -EFAULT;
- }
- bufs[i] = compat_ptr(ptr);
- bufptr++;
- }
- if (dir == SNDRV_PCM_STREAM_PLAYBACK)
- err = snd_pcm_lib_writev(substream, bufs, frames);
- else
- err = snd_pcm_lib_readv(substream, bufs, frames);
- if (err >= 0) {
- if (put_user(err, &data32->result))
- err = -EFAULT;
- }
- kfree(bufs);
- return err;
-}
-
-
-struct snd_pcm_mmap_status32 {
- s32 state;
- s32 pad1;
- u32 hw_ptr;
- struct compat_timespec tstamp;
- s32 suspended_state;
-} __attribute__((packed));
-
-struct snd_pcm_mmap_control32 {
- u32 appl_ptr;
- u32 avail_min;
-};
-
-struct snd_pcm_sync_ptr32 {
- u32 flags;
- union {
- struct snd_pcm_mmap_status32 status;
- unsigned char reserved[64];
- } s;
- union {
- struct snd_pcm_mmap_control32 control;
- unsigned char reserved[64];
- } c;
-} __attribute__((packed));
-
-static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
- struct snd_pcm_sync_ptr32 __user *src)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- volatile struct snd_pcm_mmap_status *status;
- volatile struct snd_pcm_mmap_control *control;
- u32 sflags;
- struct snd_pcm_mmap_control scontrol;
- struct snd_pcm_mmap_status sstatus;
- snd_pcm_uframes_t boundary;
- int err;
-
- if (snd_BUG_ON(!runtime))
- return -EINVAL;
-
- if (get_user(sflags, &src->flags) ||
- get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
- get_user(scontrol.avail_min, &src->c.control.avail_min))
- return -EFAULT;
- if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
- err = snd_pcm_hwsync(substream);
- if (err < 0)
- return err;
- }
- status = runtime->status;
- control = runtime->control;
- boundary = recalculate_boundary(runtime);
- if (! boundary)
- boundary = 0x7fffffff;
- snd_pcm_stream_lock_irq(substream);
- /* FIXME: we should consider the boundary for the sync from app */
- if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
- control->appl_ptr = scontrol.appl_ptr;
- else
- scontrol.appl_ptr = control->appl_ptr % boundary;
- if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
- control->avail_min = scontrol.avail_min;
- else
- scontrol.avail_min = control->avail_min;
- sstatus.state = status->state;
- sstatus.hw_ptr = status->hw_ptr % boundary;
- sstatus.tstamp = status->tstamp;
- sstatus.suspended_state = status->suspended_state;
- snd_pcm_stream_unlock_irq(substream);
- if (put_user(sstatus.state, &src->s.status.state) ||
- put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
- put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) ||
- put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) ||
- put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
- put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
- put_user(scontrol.avail_min, &src->c.control.avail_min))
- return -EFAULT;
-
- return 0;
-}
-
-
-/*
- */
-enum {
- SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32),
- SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32),
- SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32),
- SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32),
- SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
- SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32),
- SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
- SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32),
- SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct snd_xferi32),
- SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32),
- SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
- SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
- SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32),
-
-};
-
-static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream;
- void __user *argp = compat_ptr(arg);
-
- pcm_file = file->private_data;
- if (! pcm_file)
- return -ENOTTY;
- substream = pcm_file->substream;
- if (! substream)
- return -ENOTTY;
-
- /*
- * When PCM is used on 32bit mode, we need to disable
- * mmap of PCM status/control records because of the size
- * incompatibility.
- */
- pcm_file->no_compat_mmap = 1;
-
- switch (cmd) {
- case SNDRV_PCM_IOCTL_PVERSION:
- case SNDRV_PCM_IOCTL_INFO:
- case SNDRV_PCM_IOCTL_TSTAMP:
- case SNDRV_PCM_IOCTL_TTSTAMP:
- case SNDRV_PCM_IOCTL_HWSYNC:
- case SNDRV_PCM_IOCTL_PREPARE:
- case SNDRV_PCM_IOCTL_RESET:
- case SNDRV_PCM_IOCTL_START:
- case SNDRV_PCM_IOCTL_DROP:
- case SNDRV_PCM_IOCTL_DRAIN:
- case SNDRV_PCM_IOCTL_PAUSE:
- case SNDRV_PCM_IOCTL_HW_FREE:
- case SNDRV_PCM_IOCTL_RESUME:
- case SNDRV_PCM_IOCTL_XRUN:
- case SNDRV_PCM_IOCTL_LINK:
- case SNDRV_PCM_IOCTL_UNLINK:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- return snd_pcm_playback_ioctl1(file, substream, cmd, argp);
- else
- return snd_pcm_capture_ioctl1(file, substream, cmd, argp);
- case SNDRV_PCM_IOCTL_HW_REFINE32:
- return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
- case SNDRV_PCM_IOCTL_HW_PARAMS32:
- return snd_pcm_ioctl_hw_params_compat(substream, 0, argp);
- case SNDRV_PCM_IOCTL_SW_PARAMS32:
- return snd_pcm_ioctl_sw_params_compat(substream, argp);
- case SNDRV_PCM_IOCTL_STATUS32:
- return snd_pcm_status_user_compat(substream, argp);
- case SNDRV_PCM_IOCTL_SYNC_PTR32:
- return snd_pcm_ioctl_sync_ptr_compat(substream, argp);
- case SNDRV_PCM_IOCTL_CHANNEL_INFO32:
- return snd_pcm_ioctl_channel_info_compat(substream, argp);
- case SNDRV_PCM_IOCTL_WRITEI_FRAMES32:
- return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp);
- case SNDRV_PCM_IOCTL_READI_FRAMES32:
- return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp);
- case SNDRV_PCM_IOCTL_WRITEN_FRAMES32:
- return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp);
- case SNDRV_PCM_IOCTL_READN_FRAMES32:
- return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp);
- case SNDRV_PCM_IOCTL_DELAY32:
- return snd_pcm_ioctl_delay_compat(substream, argp);
- case SNDRV_PCM_IOCTL_REWIND32:
- return snd_pcm_ioctl_rewind_compat(substream, argp);
- case SNDRV_PCM_IOCTL_FORWARD32:
- return snd_pcm_ioctl_forward_compat(substream, argp);
- }
-
- return -ENOIOCTLCMD;
-}
diff --git a/ANDROID_3.4.5/sound/core/pcm_lib.c b/ANDROID_3.4.5/sound/core/pcm_lib.c
deleted file mode 100644
index 4d189411..00000000
--- a/ANDROID_3.4.5/sound/core/pcm_lib.c
+++ /dev/null
@@ -1,2289 +0,0 @@
-/*
- * Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- * Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/math64.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/info.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/timer.h>
-
-/*
- * fill ring buffer with silence
- * runtime->silence_start: starting pointer to silence area
- * runtime->silence_filled: size filled with silence
- * runtime->silence_threshold: threshold from application
- * runtime->silence_size: maximal size from application
- *
- * when runtime->silence_size >= runtime->boundary - fill processed area with silence immediately
- */
-void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_uframes_t frames, ofs, transfer;
-
- if (runtime->silence_size < runtime->boundary) {
- snd_pcm_sframes_t noise_dist, n;
- if (runtime->silence_start != runtime->control->appl_ptr) {
- n = runtime->control->appl_ptr - runtime->silence_start;
- if (n < 0)
- n += runtime->boundary;
- if ((snd_pcm_uframes_t)n < runtime->silence_filled)
- runtime->silence_filled -= n;
- else
- runtime->silence_filled = 0;
- runtime->silence_start = runtime->control->appl_ptr;
- }
- if (runtime->silence_filled >= runtime->buffer_size)
- return;
- noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
- if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold)
- return;
- frames = runtime->silence_threshold - noise_dist;
- if (frames > runtime->silence_size)
- frames = runtime->silence_size;
- } else {
- if (new_hw_ptr == ULONG_MAX) { /* initialization */
- snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime);
- if (avail > runtime->buffer_size)
- avail = runtime->buffer_size;
- runtime->silence_filled = avail > 0 ? avail : 0;
- runtime->silence_start = (runtime->status->hw_ptr +
- runtime->silence_filled) %
- runtime->boundary;
- } else {
- ofs = runtime->status->hw_ptr;
- frames = new_hw_ptr - ofs;
- if ((snd_pcm_sframes_t)frames < 0)
- frames += runtime->boundary;
- runtime->silence_filled -= frames;
- if ((snd_pcm_sframes_t)runtime->silence_filled < 0) {
- runtime->silence_filled = 0;
- runtime->silence_start = new_hw_ptr;
- } else {
- runtime->silence_start = ofs;
- }
- }
- frames = runtime->buffer_size - runtime->silence_filled;
- }
- if (snd_BUG_ON(frames > runtime->buffer_size))
- return;
- if (frames == 0)
- return;
- ofs = runtime->silence_start % runtime->buffer_size;
- while (frames > 0) {
- transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
- if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
- runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
- if (substream->ops->silence) {
- int err;
- err = substream->ops->silence(substream, -1, ofs, transfer);
- snd_BUG_ON(err < 0);
- } else {
- char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
- snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
- }
- } else {
- unsigned int c;
- unsigned int channels = runtime->channels;
- if (substream->ops->silence) {
- for (c = 0; c < channels; ++c) {
- int err;
- err = substream->ops->silence(substream, c, ofs, transfer);
- snd_BUG_ON(err < 0);
- }
- } else {
- size_t dma_csize = runtime->dma_bytes / channels;
- for (c = 0; c < channels; ++c) {
- char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs);
- snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
- }
- }
- }
- runtime->silence_filled += transfer;
- frames -= transfer;
- ofs = 0;
- }
-}
-
-#ifdef CONFIG_SND_DEBUG
-void snd_pcm_debug_name(struct snd_pcm_substream *substream,
- char *name, size_t len)
-{
- snprintf(name, len, "pcmC%dD%d%c:%d",
- substream->pcm->card->number,
- substream->pcm->device,
- substream->stream ? 'c' : 'p',
- substream->number);
-}
-EXPORT_SYMBOL(snd_pcm_debug_name);
-#endif
-
-#define XRUN_DEBUG_BASIC (1<<0)
-#define XRUN_DEBUG_STACK (1<<1) /* dump also stack */
-#define XRUN_DEBUG_JIFFIESCHECK (1<<2) /* do jiffies check */
-#define XRUN_DEBUG_PERIODUPDATE (1<<3) /* full period update info */
-#define XRUN_DEBUG_HWPTRUPDATE (1<<4) /* full hwptr update info */
-#define XRUN_DEBUG_LOG (1<<5) /* show last 10 positions on err */
-#define XRUN_DEBUG_LOGONCE (1<<6) /* do above only once */
-
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-
-#define xrun_debug(substream, mask) \
- ((substream)->pstr->xrun_debug & (mask))
-#else
-#define xrun_debug(substream, mask) 0
-#endif
-
-#define dump_stack_on_xrun(substream) do { \
- if (xrun_debug(substream, XRUN_DEBUG_STACK)) \
- dump_stack(); \
- } while (0)
-
-static void xrun(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
- snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
- snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
- if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {
- char name[16];
- snd_pcm_debug_name(substream, name, sizeof(name));
- snd_printd(KERN_DEBUG "XRUN: %s\n", name);
- dump_stack_on_xrun(substream);
- }
-}
-
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-#define hw_ptr_error(substream, fmt, args...) \
- do { \
- if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { \
- xrun_log_show(substream); \
- if (printk_ratelimit()) { \
- snd_printd("PCM: " fmt, ##args); \
- } \
- dump_stack_on_xrun(substream); \
- } \
- } while (0)
-
-#define XRUN_LOG_CNT 10
-
-struct hwptr_log_entry {
- unsigned int in_interrupt;
- unsigned long jiffies;
- snd_pcm_uframes_t pos;
- snd_pcm_uframes_t period_size;
- snd_pcm_uframes_t buffer_size;
- snd_pcm_uframes_t old_hw_ptr;
- snd_pcm_uframes_t hw_ptr_base;
-};
-
-struct snd_pcm_hwptr_log {
- unsigned int idx;
- unsigned int hit: 1;
- struct hwptr_log_entry entries[XRUN_LOG_CNT];
-};
-
-static void xrun_log(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t pos, int in_interrupt)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_pcm_hwptr_log *log = runtime->hwptr_log;
- struct hwptr_log_entry *entry;
-
- if (log == NULL) {
- log = kzalloc(sizeof(*log), GFP_ATOMIC);
- if (log == NULL)
- return;
- runtime->hwptr_log = log;
- } else {
- if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit)
- return;
- }
- entry = &log->entries[log->idx];
- entry->in_interrupt = in_interrupt;
- entry->jiffies = jiffies;
- entry->pos = pos;
- entry->period_size = runtime->period_size;
- entry->buffer_size = runtime->buffer_size;
- entry->old_hw_ptr = runtime->status->hw_ptr;
- entry->hw_ptr_base = runtime->hw_ptr_base;
- log->idx = (log->idx + 1) % XRUN_LOG_CNT;
-}
-
-static void xrun_log_show(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_hwptr_log *log = substream->runtime->hwptr_log;
- struct hwptr_log_entry *entry;
- char name[16];
- unsigned int idx;
- int cnt;
-
- if (log == NULL)
- return;
- if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit)
- return;
- snd_pcm_debug_name(substream, name, sizeof(name));
- for (cnt = 0, idx = log->idx; cnt < XRUN_LOG_CNT; cnt++) {
- entry = &log->entries[idx];
- if (entry->period_size == 0)
- break;
- snd_printd("hwptr log: %s: %sj=%lu, pos=%ld/%ld/%ld, "
- "hwptr=%ld/%ld\n",
- name, entry->in_interrupt ? "[Q] " : "",
- entry->jiffies,
- (unsigned long)entry->pos,
- (unsigned long)entry->period_size,
- (unsigned long)entry->buffer_size,
- (unsigned long)entry->old_hw_ptr,
- (unsigned long)entry->hw_ptr_base);
- idx++;
- idx %= XRUN_LOG_CNT;
- }
- log->hit = 1;
-}
-
-#else /* ! CONFIG_SND_PCM_XRUN_DEBUG */
-
-#define hw_ptr_error(substream, fmt, args...) do { } while (0)
-#define xrun_log(substream, pos, in_interrupt) do { } while (0)
-#define xrun_log_show(substream) do { } while (0)
-
-#endif
-
-int snd_pcm_update_state(struct snd_pcm_substream *substream,
- struct snd_pcm_runtime *runtime)
-{
- snd_pcm_uframes_t avail;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- avail = snd_pcm_playback_avail(runtime);
- else
- avail = snd_pcm_capture_avail(runtime);
- if (avail > runtime->avail_max)
- runtime->avail_max = avail;
- if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
- if (avail >= runtime->buffer_size) {
- snd_pcm_drain_done(substream);
- return -EPIPE;
- }
- } else {
- if (avail >= runtime->stop_threshold) {
- xrun(substream);
- return -EPIPE;
- }
- }
- if (runtime->twake) {
- if (avail >= runtime->twake)
- wake_up(&runtime->tsleep);
- } else if (avail >= runtime->control->avail_min)
- wake_up(&runtime->sleep);
- return 0;
-}
-
-static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
- unsigned int in_interrupt)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_uframes_t pos;
- snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
- snd_pcm_sframes_t hdelta, delta;
- unsigned long jdelta;
-
- old_hw_ptr = runtime->status->hw_ptr;
- pos = substream->ops->pointer(substream);
- if (pos == SNDRV_PCM_POS_XRUN) {
- xrun(substream);
- return -EPIPE;
- }
- if (pos >= runtime->buffer_size) {
- if (printk_ratelimit()) {
- char name[16];
- snd_pcm_debug_name(substream, name, sizeof(name));
- xrun_log_show(substream);
- snd_printd(KERN_ERR "BUG: %s, pos = %ld, "
- "buffer size = %ld, period size = %ld\n",
- name, pos, runtime->buffer_size,
- runtime->period_size);
- }
- pos = 0;
- }
- pos -= pos % runtime->min_align;
- if (xrun_debug(substream, XRUN_DEBUG_LOG))
- xrun_log(substream, pos, in_interrupt);
- hw_base = runtime->hw_ptr_base;
- new_hw_ptr = hw_base + pos;
- if (in_interrupt) {
- /* we know that one period was processed */
- /* delta = "expected next hw_ptr" for in_interrupt != 0 */
- delta = runtime->hw_ptr_interrupt + runtime->period_size;
- if (delta > new_hw_ptr) {
- /* check for double acknowledged interrupts */
- hdelta = jiffies - runtime->hw_ptr_jiffies;
- if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
- hw_base += runtime->buffer_size;
- if (hw_base >= runtime->boundary)
- hw_base = 0;
- new_hw_ptr = hw_base + pos;
- goto __delta;
- }
- }
- }
- /* new_hw_ptr might be lower than old_hw_ptr in case when */
- /* pointer crosses the end of the ring buffer */
- if (new_hw_ptr < old_hw_ptr) {
- hw_base += runtime->buffer_size;
- if (hw_base >= runtime->boundary)
- hw_base = 0;
- new_hw_ptr = hw_base + pos;
- }
- __delta:
- delta = new_hw_ptr - old_hw_ptr;
- if (delta < 0)
- delta += runtime->boundary;
- if (xrun_debug(substream, in_interrupt ?
- XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) {
- char name[16];
- snd_pcm_debug_name(substream, name, sizeof(name));
- snd_printd("%s_update: %s: pos=%u/%u/%u, "
- "hwptr=%ld/%ld/%ld/%ld\n",
- in_interrupt ? "period" : "hwptr",
- name,
- (unsigned int)pos,
- (unsigned int)runtime->period_size,
- (unsigned int)runtime->buffer_size,
- (unsigned long)delta,
- (unsigned long)old_hw_ptr,
- (unsigned long)new_hw_ptr,
- (unsigned long)runtime->hw_ptr_base);
- }
-
- if (runtime->no_period_wakeup) {
- snd_pcm_sframes_t xrun_threshold;
- /*
- * Without regular period interrupts, we have to check
- * the elapsed time to detect xruns.
- */
- jdelta = jiffies - runtime->hw_ptr_jiffies;
- if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)
- goto no_delta_check;
- hdelta = jdelta - delta * HZ / runtime->rate;
- xrun_threshold = runtime->hw_ptr_buffer_jiffies / 2 + 1;
- while (hdelta > xrun_threshold) {
- delta += runtime->buffer_size;
- hw_base += runtime->buffer_size;
- if (hw_base >= runtime->boundary)
- hw_base = 0;
- new_hw_ptr = hw_base + pos;
- hdelta -= runtime->hw_ptr_buffer_jiffies;
- }
- goto no_delta_check;
- }
-
- /* something must be really wrong */
- if (delta >= runtime->buffer_size + runtime->period_size) {
- hw_ptr_error(substream,
- "Unexpected hw_pointer value %s"
- "(stream=%i, pos=%ld, new_hw_ptr=%ld, "
- "old_hw_ptr=%ld)\n",
- in_interrupt ? "[Q] " : "[P]",
- substream->stream, (long)pos,
- (long)new_hw_ptr, (long)old_hw_ptr);
- return 0;
- }
-
- /* Do jiffies check only in xrun_debug mode */
- if (!xrun_debug(substream, XRUN_DEBUG_JIFFIESCHECK))
- goto no_jiffies_check;
-
- /* Skip the jiffies check for hardwares with BATCH flag.
- * Such hardware usually just increases the position at each IRQ,
- * thus it can't give any strange position.
- */
- if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
- goto no_jiffies_check;
- hdelta = delta;
- if (hdelta < runtime->delay)
- goto no_jiffies_check;
- hdelta -= runtime->delay;
- jdelta = jiffies - runtime->hw_ptr_jiffies;
- if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
- delta = jdelta /
- (((runtime->period_size * HZ) / runtime->rate)
- + HZ/100);
- /* move new_hw_ptr according jiffies not pos variable */
- new_hw_ptr = old_hw_ptr;
- hw_base = delta;
- /* use loop to avoid checks for delta overflows */
- /* the delta value is small or zero in most cases */
- while (delta > 0) {
- new_hw_ptr += runtime->period_size;
- if (new_hw_ptr >= runtime->boundary)
- new_hw_ptr -= runtime->boundary;
- delta--;
- }
- /* align hw_base to buffer_size */
- hw_ptr_error(substream,
- "hw_ptr skipping! %s"
- "(pos=%ld, delta=%ld, period=%ld, "
- "jdelta=%lu/%lu/%lu, hw_ptr=%ld/%ld)\n",
- in_interrupt ? "[Q] " : "",
- (long)pos, (long)hdelta,
- (long)runtime->period_size, jdelta,
- ((hdelta * HZ) / runtime->rate), hw_base,
- (unsigned long)old_hw_ptr,
- (unsigned long)new_hw_ptr);
- /* reset values to proper state */
- delta = 0;
- hw_base = new_hw_ptr - (new_hw_ptr % runtime->buffer_size);
- }
- no_jiffies_check:
- if (delta > runtime->period_size + runtime->period_size / 2) {
- hw_ptr_error(substream,
- "Lost interrupts? %s"
- "(stream=%i, delta=%ld, new_hw_ptr=%ld, "
- "old_hw_ptr=%ld)\n",
- in_interrupt ? "[Q] " : "",
- substream->stream, (long)delta,
- (long)new_hw_ptr,
- (long)old_hw_ptr);
- }
-
- no_delta_check:
- if (runtime->status->hw_ptr == new_hw_ptr)
- return 0;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
- runtime->silence_size > 0)
- snd_pcm_playback_silence(substream, new_hw_ptr);
-
- if (in_interrupt) {
- delta = new_hw_ptr - runtime->hw_ptr_interrupt;
- if (delta < 0)
- delta += runtime->boundary;
- delta -= (snd_pcm_uframes_t)delta % runtime->period_size;
- runtime->hw_ptr_interrupt += delta;
- if (runtime->hw_ptr_interrupt >= runtime->boundary)
- runtime->hw_ptr_interrupt -= runtime->boundary;
- }
- runtime->hw_ptr_base = hw_base;
- runtime->status->hw_ptr = new_hw_ptr;
- runtime->hw_ptr_jiffies = jiffies;
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
- snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
-
- return snd_pcm_update_state(substream, runtime);
-}
-
-/* CAUTION: call it with irq disabled */
-int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
-{
- return snd_pcm_update_hw_ptr0(substream, 0);
-}
-
-/**
- * snd_pcm_set_ops - set the PCM operators
- * @pcm: the pcm instance
- * @direction: stream direction, SNDRV_PCM_STREAM_XXX
- * @ops: the operator table
- *
- * Sets the given PCM operators to the pcm instance.
- */
-void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, struct snd_pcm_ops *ops)
-{
- struct snd_pcm_str *stream = &pcm->streams[direction];
- struct snd_pcm_substream *substream;
-
- for (substream = stream->substream; substream != NULL; substream = substream->next)
- substream->ops = ops;
-}
-
-EXPORT_SYMBOL(snd_pcm_set_ops);
-
-/**
- * snd_pcm_sync - set the PCM sync id
- * @substream: the pcm substream
- *
- * Sets the PCM sync identifier for the card.
- */
-void snd_pcm_set_sync(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- runtime->sync.id32[0] = substream->pcm->card->number;
- runtime->sync.id32[1] = -1;
- runtime->sync.id32[2] = -1;
- runtime->sync.id32[3] = -1;
-}
-
-EXPORT_SYMBOL(snd_pcm_set_sync);
-
-/*
- * Standard ioctl routine
- */
-
-static inline unsigned int div32(unsigned int a, unsigned int b,
- unsigned int *r)
-{
- if (b == 0) {
- *r = 0;
- return UINT_MAX;
- }
- *r = a % b;
- return a / b;
-}
-
-static inline unsigned int div_down(unsigned int a, unsigned int b)
-{
- if (b == 0)
- return UINT_MAX;
- return a / b;
-}
-
-static inline unsigned int div_up(unsigned int a, unsigned int b)
-{
- unsigned int r;
- unsigned int q;
- if (b == 0)
- return UINT_MAX;
- q = div32(a, b, &r);
- if (r)
- ++q;
- return q;
-}
-
-static inline unsigned int mul(unsigned int a, unsigned int b)
-{
- if (a == 0)
- return 0;
- if (div_down(UINT_MAX, a) < b)
- return UINT_MAX;
- return a * b;
-}
-
-static inline unsigned int muldiv32(unsigned int a, unsigned int b,
- unsigned int c, unsigned int *r)
-{
- u_int64_t n = (u_int64_t) a * b;
- if (c == 0) {
- snd_BUG_ON(!n);
- *r = 0;
- return UINT_MAX;
- }
- n = div_u64_rem(n, c, r);
- if (n >= UINT_MAX) {
- *r = 0;
- return UINT_MAX;
- }
- return n;
-}
-
-/**
- * snd_interval_refine - refine the interval value of configurator
- * @i: the interval value to refine
- * @v: the interval value to refer to
- *
- * Refines the interval value with the reference value.
- * The interval is changed to the range satisfying both intervals.
- * The interval status (min, max, integer, etc.) are evaluated.
- *
- * Returns non-zero if the value is changed, zero if not changed.
- */
-int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
-{
- int changed = 0;
- if (snd_BUG_ON(snd_interval_empty(i)))
- return -EINVAL;
- if (i->min < v->min) {
- i->min = v->min;
- i->openmin = v->openmin;
- changed = 1;
- } else if (i->min == v->min && !i->openmin && v->openmin) {
- i->openmin = 1;
- changed = 1;
- }
- if (i->max > v->max) {
- i->max = v->max;
- i->openmax = v->openmax;
- changed = 1;
- } else if (i->max == v->max && !i->openmax && v->openmax) {
- i->openmax = 1;
- changed = 1;
- }
- if (!i->integer && v->integer) {
- i->integer = 1;
- changed = 1;
- }
- if (i->integer) {
- if (i->openmin) {
- i->min++;
- i->openmin = 0;
- }
- if (i->openmax) {
- i->max--;
- i->openmax = 0;
- }
- } else if (!i->openmin && !i->openmax && i->min == i->max)
- i->integer = 1;
- if (snd_interval_checkempty(i)) {
- snd_interval_none(i);
- return -EINVAL;
- }
- return changed;
-}
-
-EXPORT_SYMBOL(snd_interval_refine);
-
-static int snd_interval_refine_first(struct snd_interval *i)
-{
- if (snd_BUG_ON(snd_interval_empty(i)))
- return -EINVAL;
- if (snd_interval_single(i))
- return 0;
- i->max = i->min;
- i->openmax = i->openmin;
- if (i->openmax)
- i->max++;
- return 1;
-}
-
-static int snd_interval_refine_last(struct snd_interval *i)
-{
- if (snd_BUG_ON(snd_interval_empty(i)))
- return -EINVAL;
- if (snd_interval_single(i))
- return 0;
- i->min = i->max;
- i->openmin = i->openmax;
- if (i->openmin)
- i->min--;
- return 1;
-}
-
-void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c)
-{
- if (a->empty || b->empty) {
- snd_interval_none(c);
- return;
- }
- c->empty = 0;
- c->min = mul(a->min, b->min);
- c->openmin = (a->openmin || b->openmin);
- c->max = mul(a->max, b->max);
- c->openmax = (a->openmax || b->openmax);
- c->integer = (a->integer && b->integer);
-}
-
-/**
- * snd_interval_div - refine the interval value with division
- * @a: dividend
- * @b: divisor
- * @c: quotient
- *
- * c = a / b
- *
- * Returns non-zero if the value is changed, zero if not changed.
- */
-void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c)
-{
- unsigned int r;
- if (a->empty || b->empty) {
- snd_interval_none(c);
- return;
- }
- c->empty = 0;
- c->min = div32(a->min, b->max, &r);
- c->openmin = (r || a->openmin || b->openmax);
- if (b->min > 0) {
- c->max = div32(a->max, b->min, &r);
- if (r) {
- c->max++;
- c->openmax = 1;
- } else
- c->openmax = (a->openmax || b->openmin);
- } else {
- c->max = UINT_MAX;
- c->openmax = 0;
- }
- c->integer = 0;
-}
-
-/**
- * snd_interval_muldivk - refine the interval value
- * @a: dividend 1
- * @b: dividend 2
- * @k: divisor (as integer)
- * @c: result
- *
- * c = a * b / k
- *
- * Returns non-zero if the value is changed, zero if not changed.
- */
-void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b,
- unsigned int k, struct snd_interval *c)
-{
- unsigned int r;
- if (a->empty || b->empty) {
- snd_interval_none(c);
- return;
- }
- c->empty = 0;
- c->min = muldiv32(a->min, b->min, k, &r);
- c->openmin = (r || a->openmin || b->openmin);
- c->max = muldiv32(a->max, b->max, k, &r);
- if (r) {
- c->max++;
- c->openmax = 1;
- } else
- c->openmax = (a->openmax || b->openmax);
- c->integer = 0;
-}
-
-/**
- * snd_interval_mulkdiv - refine the interval value
- * @a: dividend 1
- * @k: dividend 2 (as integer)
- * @b: divisor
- * @c: result
- *
- * c = a * k / b
- *
- * Returns non-zero if the value is changed, zero if not changed.
- */
-void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
- const struct snd_interval *b, struct snd_interval *c)
-{
- unsigned int r;
- if (a->empty || b->empty) {
- snd_interval_none(c);
- return;
- }
- c->empty = 0;
- c->min = muldiv32(a->min, k, b->max, &r);
- c->openmin = (r || a->openmin || b->openmax);
- if (b->min > 0) {
- c->max = muldiv32(a->max, k, b->min, &r);
- if (r) {
- c->max++;
- c->openmax = 1;
- } else
- c->openmax = (a->openmax || b->openmin);
- } else {
- c->max = UINT_MAX;
- c->openmax = 0;
- }
- c->integer = 0;
-}
-
-/* ---- */
-
-
-/**
- * snd_interval_ratnum - refine the interval value
- * @i: interval to refine
- * @rats_count: number of ratnum_t
- * @rats: ratnum_t array
- * @nump: pointer to store the resultant numerator
- * @denp: pointer to store the resultant denominator
- *
- * Returns non-zero if the value is changed, zero if not changed.
- */
-int snd_interval_ratnum(struct snd_interval *i,
- unsigned int rats_count, struct snd_ratnum *rats,
- unsigned int *nump, unsigned int *denp)
-{
- unsigned int best_num, best_den;
- int best_diff;
- unsigned int k;
- struct snd_interval t;
- int err;
- unsigned int result_num, result_den;
- int result_diff;
-
- best_num = best_den = best_diff = 0;
- for (k = 0; k < rats_count; ++k) {
- unsigned int num = rats[k].num;
- unsigned int den;
- unsigned int q = i->min;
- int diff;
- if (q == 0)
- q = 1;
- den = div_up(num, q);
- if (den < rats[k].den_min)
- continue;
- if (den > rats[k].den_max)
- den = rats[k].den_max;
- else {
- unsigned int r;
- r = (den - rats[k].den_min) % rats[k].den_step;
- if (r != 0)
- den -= r;
- }
- diff = num - q * den;
- if (diff < 0)
- diff = -diff;
- if (best_num == 0 ||
- diff * best_den < best_diff * den) {
- best_diff = diff;
- best_den = den;
- best_num = num;
- }
- }
- if (best_den == 0) {
- i->empty = 1;
- return -EINVAL;
- }
- t.min = div_down(best_num, best_den);
- t.openmin = !!(best_num % best_den);
-
- result_num = best_num;
- result_diff = best_diff;
- result_den = best_den;
- best_num = best_den = best_diff = 0;
- for (k = 0; k < rats_count; ++k) {
- unsigned int num = rats[k].num;
- unsigned int den;
- unsigned int q = i->max;
- int diff;
- if (q == 0) {
- i->empty = 1;
- return -EINVAL;
- }
- den = div_down(num, q);
- if (den > rats[k].den_max)
- continue;
- if (den < rats[k].den_min)
- den = rats[k].den_min;
- else {
- unsigned int r;
- r = (den - rats[k].den_min) % rats[k].den_step;
- if (r != 0)
- den += rats[k].den_step - r;
- }
- diff = q * den - num;
- if (diff < 0)
- diff = -diff;
- if (best_num == 0 ||
- diff * best_den < best_diff * den) {
- best_diff = diff;
- best_den = den;
- best_num = num;
- }
- }
- if (best_den == 0) {
- i->empty = 1;
- return -EINVAL;
- }
- t.max = div_up(best_num, best_den);
- t.openmax = !!(best_num % best_den);
- t.integer = 0;
- err = snd_interval_refine(i, &t);
- if (err < 0)
- return err;
-
- if (snd_interval_single(i)) {
- if (best_diff * result_den < result_diff * best_den) {
- result_num = best_num;
- result_den = best_den;
- }
- if (nump)
- *nump = result_num;
- if (denp)
- *denp = result_den;
- }
- return err;
-}
-
-EXPORT_SYMBOL(snd_interval_ratnum);
-
-/**
- * snd_interval_ratden - refine the interval value
- * @i: interval to refine
- * @rats_count: number of struct ratden
- * @rats: struct ratden array
- * @nump: pointer to store the resultant numerator
- * @denp: pointer to store the resultant denominator
- *
- * Returns non-zero if the value is changed, zero if not changed.
- */
-static int snd_interval_ratden(struct snd_interval *i,
- unsigned int rats_count, struct snd_ratden *rats,
- unsigned int *nump, unsigned int *denp)
-{
- unsigned int best_num, best_diff, best_den;
- unsigned int k;
- struct snd_interval t;
- int err;
-
- best_num = best_den = best_diff = 0;
- for (k = 0; k < rats_count; ++k) {
- unsigned int num;
- unsigned int den = rats[k].den;
- unsigned int q = i->min;
- int diff;
- num = mul(q, den);
- if (num > rats[k].num_max)
- continue;
- if (num < rats[k].num_min)
- num = rats[k].num_max;
- else {
- unsigned int r;
- r = (num - rats[k].num_min) % rats[k].num_step;
- if (r != 0)
- num += rats[k].num_step - r;
- }
- diff = num - q * den;
- if (best_num == 0 ||
- diff * best_den < best_diff * den) {
- best_diff = diff;
- best_den = den;
- best_num = num;
- }
- }
- if (best_den == 0) {
- i->empty = 1;
- return -EINVAL;
- }
- t.min = div_down(best_num, best_den);
- t.openmin = !!(best_num % best_den);
-
- best_num = best_den = best_diff = 0;
- for (k = 0; k < rats_count; ++k) {
- unsigned int num;
- unsigned int den = rats[k].den;
- unsigned int q = i->max;
- int diff;
- num = mul(q, den);
- if (num < rats[k].num_min)
- continue;
- if (num > rats[k].num_max)
- num = rats[k].num_max;
- else {
- unsigned int r;
- r = (num - rats[k].num_min) % rats[k].num_step;
- if (r != 0)
- num -= r;
- }
- diff = q * den - num;
- if (best_num == 0 ||
- diff * best_den < best_diff * den) {
- best_diff = diff;
- best_den = den;
- best_num = num;
- }
- }
- if (best_den == 0) {
- i->empty = 1;
- return -EINVAL;
- }
- t.max = div_up(best_num, best_den);
- t.openmax = !!(best_num % best_den);
- t.integer = 0;
- err = snd_interval_refine(i, &t);
- if (err < 0)
- return err;
-
- if (snd_interval_single(i)) {
- if (nump)
- *nump = best_num;
- if (denp)
- *denp = best_den;
- }
- return err;
-}
-
-/**
- * snd_interval_list - refine the interval value from the list
- * @i: the interval value to refine
- * @count: the number of elements in the list
- * @list: the value list
- * @mask: the bit-mask to evaluate
- *
- * Refines the interval value from the list.
- * When mask is non-zero, only the elements corresponding to bit 1 are
- * evaluated.
- *
- * Returns non-zero if the value is changed, zero if not changed.
- */
-int snd_interval_list(struct snd_interval *i, unsigned int count,
- const unsigned int *list, unsigned int mask)
-{
- unsigned int k;
- struct snd_interval list_range;
-
- if (!count) {
- i->empty = 1;
- return -EINVAL;
- }
- snd_interval_any(&list_range);
- list_range.min = UINT_MAX;
- list_range.max = 0;
- for (k = 0; k < count; k++) {
- if (mask && !(mask & (1 << k)))
- continue;
- if (!snd_interval_test(i, list[k]))
- continue;
- list_range.min = min(list_range.min, list[k]);
- list_range.max = max(list_range.max, list[k]);
- }
- return snd_interval_refine(i, &list_range);
-}
-
-EXPORT_SYMBOL(snd_interval_list);
-
-static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step)
-{
- unsigned int n;
- int changed = 0;
- n = (i->min - min) % step;
- if (n != 0 || i->openmin) {
- i->min += step - n;
- changed = 1;
- }
- n = (i->max - min) % step;
- if (n != 0 || i->openmax) {
- i->max -= n;
- changed = 1;
- }
- if (snd_interval_checkempty(i)) {
- i->empty = 1;
- return -EINVAL;
- }
- return changed;
-}
-
-/* Info constraints helpers */
-
-/**
- * snd_pcm_hw_rule_add - add the hw-constraint rule
- * @runtime: the pcm runtime instance
- * @cond: condition bits
- * @var: the variable to evaluate
- * @func: the evaluation function
- * @private: the private data pointer passed to function
- * @dep: the dependent variables
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
- int var,
- snd_pcm_hw_rule_func_t func, void *private,
- int dep, ...)
-{
- struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
- struct snd_pcm_hw_rule *c;
- unsigned int k;
- va_list args;
- va_start(args, dep);
- if (constrs->rules_num >= constrs->rules_all) {
- struct snd_pcm_hw_rule *new;
- unsigned int new_rules = constrs->rules_all + 16;
- new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL);
- if (!new) {
- va_end(args);
- return -ENOMEM;
- }
- if (constrs->rules) {
- memcpy(new, constrs->rules,
- constrs->rules_num * sizeof(*c));
- kfree(constrs->rules);
- }
- constrs->rules = new;
- constrs->rules_all = new_rules;
- }
- c = &constrs->rules[constrs->rules_num];
- c->cond = cond;
- c->func = func;
- c->var = var;
- c->private = private;
- k = 0;
- while (1) {
- if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps))) {
- va_end(args);
- return -EINVAL;
- }
- c->deps[k++] = dep;
- if (dep < 0)
- break;
- dep = va_arg(args, int);
- }
- constrs->rules_num++;
- va_end(args);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_rule_add);
-
-/**
- * snd_pcm_hw_constraint_mask - apply the given bitmap mask constraint
- * @runtime: PCM runtime instance
- * @var: hw_params variable to apply the mask
- * @mask: the bitmap mask
- *
- * Apply the constraint of the given bitmap mask to a 32-bit mask parameter.
- */
-int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
- u_int32_t mask)
-{
- struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
- struct snd_mask *maskp = constrs_mask(constrs, var);
- *maskp->bits &= mask;
- memset(maskp->bits + 1, 0, (SNDRV_MASK_MAX-32) / 8); /* clear rest */
- if (*maskp->bits == 0)
- return -EINVAL;
- return 0;
-}
-
-/**
- * snd_pcm_hw_constraint_mask64 - apply the given bitmap mask constraint
- * @runtime: PCM runtime instance
- * @var: hw_params variable to apply the mask
- * @mask: the 64bit bitmap mask
- *
- * Apply the constraint of the given bitmap mask to a 64-bit mask parameter.
- */
-int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
- u_int64_t mask)
-{
- struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
- struct snd_mask *maskp = constrs_mask(constrs, var);
- maskp->bits[0] &= (u_int32_t)mask;
- maskp->bits[1] &= (u_int32_t)(mask >> 32);
- memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */
- if (! maskp->bits[0] && ! maskp->bits[1])
- return -EINVAL;
- return 0;
-}
-
-/**
- * snd_pcm_hw_constraint_integer - apply an integer constraint to an interval
- * @runtime: PCM runtime instance
- * @var: hw_params variable to apply the integer constraint
- *
- * Apply the constraint of integer to an interval parameter.
- */
-int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var)
-{
- struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
- return snd_interval_setinteger(constrs_interval(constrs, var));
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
-
-/**
- * snd_pcm_hw_constraint_minmax - apply a min/max range constraint to an interval
- * @runtime: PCM runtime instance
- * @var: hw_params variable to apply the range
- * @min: the minimal value
- * @max: the maximal value
- *
- * Apply the min/max range constraint to an interval parameter.
- */
-int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
- unsigned int min, unsigned int max)
-{
- struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
- struct snd_interval t;
- t.min = min;
- t.max = max;
- t.openmin = t.openmax = 0;
- t.integer = 0;
- return snd_interval_refine(constrs_interval(constrs, var), &t);
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
-
-static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_pcm_hw_constraint_list *list = rule->private;
- return snd_interval_list(hw_param_interval(params, rule->var), list->count, list->list, list->mask);
-}
-
-
-/**
- * snd_pcm_hw_constraint_list - apply a list of constraints to a parameter
- * @runtime: PCM runtime instance
- * @cond: condition bits
- * @var: hw_params variable to apply the list constraint
- * @l: list
- *
- * Apply the list of constraints to an interval parameter.
- */
-int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
- unsigned int cond,
- snd_pcm_hw_param_t var,
- struct snd_pcm_hw_constraint_list *l)
-{
- return snd_pcm_hw_rule_add(runtime, cond, var,
- snd_pcm_hw_rule_list, l,
- var, -1);
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
-
-static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_pcm_hw_constraint_ratnums *r = rule->private;
- unsigned int num = 0, den = 0;
- int err;
- err = snd_interval_ratnum(hw_param_interval(params, rule->var),
- r->nrats, r->rats, &num, &den);
- if (err >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) {
- params->rate_num = num;
- params->rate_den = den;
- }
- return err;
-}
-
-/**
- * snd_pcm_hw_constraint_ratnums - apply ratnums constraint to a parameter
- * @runtime: PCM runtime instance
- * @cond: condition bits
- * @var: hw_params variable to apply the ratnums constraint
- * @r: struct snd_ratnums constriants
- */
-int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
- unsigned int cond,
- snd_pcm_hw_param_t var,
- struct snd_pcm_hw_constraint_ratnums *r)
-{
- return snd_pcm_hw_rule_add(runtime, cond, var,
- snd_pcm_hw_rule_ratnums, r,
- var, -1);
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
-
-static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_pcm_hw_constraint_ratdens *r = rule->private;
- unsigned int num = 0, den = 0;
- int err = snd_interval_ratden(hw_param_interval(params, rule->var),
- r->nrats, r->rats, &num, &den);
- if (err >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) {
- params->rate_num = num;
- params->rate_den = den;
- }
- return err;
-}
-
-/**
- * snd_pcm_hw_constraint_ratdens - apply ratdens constraint to a parameter
- * @runtime: PCM runtime instance
- * @cond: condition bits
- * @var: hw_params variable to apply the ratdens constraint
- * @r: struct snd_ratdens constriants
- */
-int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
- unsigned int cond,
- snd_pcm_hw_param_t var,
- struct snd_pcm_hw_constraint_ratdens *r)
-{
- return snd_pcm_hw_rule_add(runtime, cond, var,
- snd_pcm_hw_rule_ratdens, r,
- var, -1);
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
-
-static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- unsigned int l = (unsigned long) rule->private;
- int width = l & 0xffff;
- unsigned int msbits = l >> 16;
- struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
- if (snd_interval_single(i) && snd_interval_value(i) == width)
- params->msbits = msbits;
- return 0;
-}
-
-/**
- * snd_pcm_hw_constraint_msbits - add a hw constraint msbits rule
- * @runtime: PCM runtime instance
- * @cond: condition bits
- * @width: sample bits width
- * @msbits: msbits width
- */
-int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
- unsigned int cond,
- unsigned int width,
- unsigned int msbits)
-{
- unsigned long l = (msbits << 16) | width;
- return snd_pcm_hw_rule_add(runtime, cond, -1,
- snd_pcm_hw_rule_msbits,
- (void*) l,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
-
-static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- unsigned long step = (unsigned long) rule->private;
- return snd_interval_step(hw_param_interval(params, rule->var), 0, step);
-}
-
-/**
- * snd_pcm_hw_constraint_step - add a hw constraint step rule
- * @runtime: PCM runtime instance
- * @cond: condition bits
- * @var: hw_params variable to apply the step constraint
- * @step: step size
- */
-int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
- unsigned int cond,
- snd_pcm_hw_param_t var,
- unsigned long step)
-{
- return snd_pcm_hw_rule_add(runtime, cond, var,
- snd_pcm_hw_rule_step, (void *) step,
- var, -1);
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
-
-static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
-{
- static unsigned int pow2_sizes[] = {
- 1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7,
- 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15,
- 1<<16, 1<<17, 1<<18, 1<<19, 1<<20, 1<<21, 1<<22, 1<<23,
- 1<<24, 1<<25, 1<<26, 1<<27, 1<<28, 1<<29, 1<<30
- };
- return snd_interval_list(hw_param_interval(params, rule->var),
- ARRAY_SIZE(pow2_sizes), pow2_sizes, 0);
-}
-
-/**
- * snd_pcm_hw_constraint_pow2 - add a hw constraint power-of-2 rule
- * @runtime: PCM runtime instance
- * @cond: condition bits
- * @var: hw_params variable to apply the power-of-2 constraint
- */
-int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
- unsigned int cond,
- snd_pcm_hw_param_t var)
-{
- return snd_pcm_hw_rule_add(runtime, cond, var,
- snd_pcm_hw_rule_pow2, NULL,
- var, -1);
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
-
-static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- unsigned int base_rate = (unsigned int)(uintptr_t)rule->private;
- struct snd_interval *rate;
-
- rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
- return snd_interval_list(rate, 1, &base_rate, 0);
-}
-
-/**
- * snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling
- * @runtime: PCM runtime instance
- * @base_rate: the rate at which the hardware does not resample
- */
-int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime,
- unsigned int base_rate)
-{
- return snd_pcm_hw_rule_add(runtime, SNDRV_PCM_HW_PARAMS_NORESAMPLE,
- SNDRV_PCM_HW_PARAM_RATE,
- snd_pcm_hw_rule_noresample_func,
- (void *)(uintptr_t)base_rate,
- SNDRV_PCM_HW_PARAM_RATE, -1);
-}
-EXPORT_SYMBOL(snd_pcm_hw_rule_noresample);
-
-static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var)
-{
- if (hw_is_mask(var)) {
- snd_mask_any(hw_param_mask(params, var));
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- return;
- }
- if (hw_is_interval(var)) {
- snd_interval_any(hw_param_interval(params, var));
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- return;
- }
- snd_BUG();
-}
-
-void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
-{
- unsigned int k;
- memset(params, 0, sizeof(*params));
- for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++)
- _snd_pcm_hw_param_any(params, k);
- for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
- _snd_pcm_hw_param_any(params, k);
- params->info = ~0U;
-}
-
-EXPORT_SYMBOL(_snd_pcm_hw_params_any);
-
-/**
- * snd_pcm_hw_param_value - return @params field @var value
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or %NULL
- *
- * Return the value for field @var if it's fixed in configuration space
- * defined by @params. Return -%EINVAL otherwise.
- */
-int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, int *dir)
-{
- if (hw_is_mask(var)) {
- const struct snd_mask *mask = hw_param_mask_c(params, var);
- if (!snd_mask_single(mask))
- return -EINVAL;
- if (dir)
- *dir = 0;
- return snd_mask_value(mask);
- }
- if (hw_is_interval(var)) {
- const struct snd_interval *i = hw_param_interval_c(params, var);
- if (!snd_interval_single(i))
- return -EINVAL;
- if (dir)
- *dir = i->openmin;
- return snd_interval_value(i);
- }
- return -EINVAL;
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_param_value);
-
-void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var)
-{
- if (hw_is_mask(var)) {
- snd_mask_none(hw_param_mask(params, var));
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- } else if (hw_is_interval(var)) {
- snd_interval_none(hw_param_interval(params, var));
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- } else {
- snd_BUG();
- }
-}
-
-EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
-
-static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var)
-{
- int changed;
- if (hw_is_mask(var))
- changed = snd_mask_refine_first(hw_param_mask(params, var));
- else if (hw_is_interval(var))
- changed = snd_interval_refine_first(hw_param_interval(params, var));
- else
- return -EINVAL;
- if (changed) {
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- }
- return changed;
-}
-
-
-/**
- * snd_pcm_hw_param_first - refine config space and return minimum value
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or %NULL
- *
- * Inside configuration space defined by @params remove from @var all
- * values > minimum. Reduce configuration space accordingly.
- * Return the minimum.
- */
-int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
- struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, int *dir)
-{
- int changed = _snd_pcm_hw_param_first(params, var);
- if (changed < 0)
- return changed;
- if (params->rmask) {
- int err = snd_pcm_hw_refine(pcm, params);
- if (snd_BUG_ON(err < 0))
- return err;
- }
- return snd_pcm_hw_param_value(params, var, dir);
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_param_first);
-
-static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var)
-{
- int changed;
- if (hw_is_mask(var))
- changed = snd_mask_refine_last(hw_param_mask(params, var));
- else if (hw_is_interval(var))
- changed = snd_interval_refine_last(hw_param_interval(params, var));
- else
- return -EINVAL;
- if (changed) {
- params->cmask |= 1 << var;
- params->rmask |= 1 << var;
- }
- return changed;
-}
-
-
-/**
- * snd_pcm_hw_param_last - refine config space and return maximum value
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or %NULL
- *
- * Inside configuration space defined by @params remove from @var all
- * values < maximum. Reduce configuration space accordingly.
- * Return the maximum.
- */
-int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
- struct snd_pcm_hw_params *params,
- snd_pcm_hw_param_t var, int *dir)
-{
- int changed = _snd_pcm_hw_param_last(params, var);
- if (changed < 0)
- return changed;
- if (params->rmask) {
- int err = snd_pcm_hw_refine(pcm, params);
- if (snd_BUG_ON(err < 0))
- return err;
- }
- return snd_pcm_hw_param_value(params, var, dir);
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_param_last);
-
-/**
- * snd_pcm_hw_param_choose - choose a configuration defined by @params
- * @pcm: PCM instance
- * @params: the hw_params instance
- *
- * Choose one configuration from configuration space defined by @params.
- * The configuration chosen is that obtained fixing in this order:
- * first access, first format, first subformat, min channels,
- * min rate, min period time, max buffer size, min tick time
- */
-int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
- struct snd_pcm_hw_params *params)
-{
- static int vars[] = {
- SNDRV_PCM_HW_PARAM_ACCESS,
- SNDRV_PCM_HW_PARAM_FORMAT,
- SNDRV_PCM_HW_PARAM_SUBFORMAT,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- SNDRV_PCM_HW_PARAM_RATE,
- SNDRV_PCM_HW_PARAM_PERIOD_TIME,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
- SNDRV_PCM_HW_PARAM_TICK_TIME,
- -1
- };
- int err, *v;
-
- for (v = vars; *v != -1; v++) {
- if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
- err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
- else
- err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
- if (snd_BUG_ON(err < 0))
- return err;
- }
- return 0;
-}
-
-static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
- void *arg)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long flags;
- snd_pcm_stream_lock_irqsave(substream, flags);
- if (snd_pcm_running(substream) &&
- snd_pcm_update_hw_ptr(substream) >= 0)
- runtime->status->hw_ptr %= runtime->buffer_size;
- else
- runtime->status->hw_ptr = 0;
- snd_pcm_stream_unlock_irqrestore(substream, flags);
- return 0;
-}
-
-static int snd_pcm_lib_ioctl_channel_info(struct snd_pcm_substream *substream,
- void *arg)
-{
- struct snd_pcm_channel_info *info = arg;
- struct snd_pcm_runtime *runtime = substream->runtime;
- int width;
- if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) {
- info->offset = -1;
- return 0;
- }
- width = snd_pcm_format_physical_width(runtime->format);
- if (width < 0)
- return width;
- info->offset = 0;
- switch (runtime->access) {
- case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED:
- case SNDRV_PCM_ACCESS_RW_INTERLEAVED:
- info->first = info->channel * width;
- info->step = runtime->channels * width;
- break;
- case SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED:
- case SNDRV_PCM_ACCESS_RW_NONINTERLEAVED:
- {
- size_t size = runtime->dma_bytes / runtime->channels;
- info->first = info->channel * size * 8;
- info->step = width;
- break;
- }
- default:
- snd_BUG();
- break;
- }
- return 0;
-}
-
-static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
- void *arg)
-{
- struct snd_pcm_hw_params *params = arg;
- snd_pcm_format_t format;
- int channels, width;
-
- params->fifo_size = substream->runtime->hw.fifo_size;
- if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_FIFO_IN_FRAMES)) {
- format = params_format(params);
- channels = params_channels(params);
- width = snd_pcm_format_physical_width(format);
- params->fifo_size /= width * channels;
- }
- return 0;
-}
-
-/**
- * snd_pcm_lib_ioctl - a generic PCM ioctl callback
- * @substream: the pcm substream instance
- * @cmd: ioctl command
- * @arg: ioctl argument
- *
- * Processes the generic ioctl commands for PCM.
- * Can be passed as the ioctl callback for PCM ops.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
- switch (cmd) {
- case SNDRV_PCM_IOCTL1_INFO:
- return 0;
- case SNDRV_PCM_IOCTL1_RESET:
- return snd_pcm_lib_ioctl_reset(substream, arg);
- case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
- return snd_pcm_lib_ioctl_channel_info(substream, arg);
- case SNDRV_PCM_IOCTL1_FIFO_SIZE:
- return snd_pcm_lib_ioctl_fifo_size(substream, arg);
- }
- return -ENXIO;
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_ioctl);
-
-/**
- * snd_pcm_period_elapsed - update the pcm status for the next period
- * @substream: the pcm substream instance
- *
- * This function is called from the interrupt handler when the
- * PCM has processed the period size. It will update the current
- * pointer, wake up sleepers, etc.
- *
- * Even if more than one periods have elapsed since the last call, you
- * have to call this only once.
- */
-void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
- unsigned long flags;
-
- if (PCM_RUNTIME_CHECK(substream))
- return;
- runtime = substream->runtime;
-
- if (runtime->transfer_ack_begin)
- runtime->transfer_ack_begin(substream);
-
- snd_pcm_stream_lock_irqsave(substream, flags);
- if (!snd_pcm_running(substream) ||
- snd_pcm_update_hw_ptr0(substream, 1) < 0)
- goto _end;
-
- if (substream->timer_running)
- snd_timer_interrupt(substream->timer, 1);
- _end:
- snd_pcm_stream_unlock_irqrestore(substream, flags);
- if (runtime->transfer_ack_end)
- runtime->transfer_ack_end(substream);
- kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
-}
-
-EXPORT_SYMBOL(snd_pcm_period_elapsed);
-
-/*
- * Wait until avail_min data becomes available
- * Returns a negative error code if any error occurs during operation.
- * The available space is stored on availp. When err = 0 and avail = 0
- * on the capture stream, it indicates the stream is in DRAINING state.
- */
-static int wait_for_avail(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t *availp)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- wait_queue_t wait;
- int err = 0;
- snd_pcm_uframes_t avail = 0;
- long wait_time, tout;
-
- init_waitqueue_entry(&wait, current);
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&runtime->tsleep, &wait);
-
- if (runtime->no_period_wakeup)
- wait_time = MAX_SCHEDULE_TIMEOUT;
- else {
- wait_time = 10;
- if (runtime->rate) {
- long t = runtime->period_size * 2 / runtime->rate;
- wait_time = max(t, wait_time);
- }
- wait_time = msecs_to_jiffies(wait_time * 1000);
- }
-
- for (;;) {
- if (signal_pending(current)) {
- err = -ERESTARTSYS;
- break;
- }
-
- /*
- * We need to check if space became available already
- * (and thus the wakeup happened already) first to close
- * the race of space already having become available.
- * This check must happen after been added to the waitqueue
- * and having current state be INTERRUPTIBLE.
- */
- if (is_playback)
- avail = snd_pcm_playback_avail(runtime);
- else
- avail = snd_pcm_capture_avail(runtime);
- if (avail >= runtime->twake)
- break;
- snd_pcm_stream_unlock_irq(substream);
-
- tout = schedule_timeout(wait_time);
-
- snd_pcm_stream_lock_irq(substream);
- set_current_state(TASK_INTERRUPTIBLE);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
- goto _endloop;
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- goto _endloop;
- case SNDRV_PCM_STATE_DRAINING:
- if (is_playback)
- err = -EPIPE;
- else
- avail = 0; /* indicate draining */
- goto _endloop;
- case SNDRV_PCM_STATE_OPEN:
- case SNDRV_PCM_STATE_SETUP:
- case SNDRV_PCM_STATE_DISCONNECTED:
- err = -EBADFD;
- goto _endloop;
- }
- if (!tout) {
- snd_printd("%s write error (DMA or IRQ trouble?)\n",
- is_playback ? "playback" : "capture");
- err = -EIO;
- break;
- }
- }
- _endloop:
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&runtime->tsleep, &wait);
- *availp = avail;
- return err;
-}
-
-static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
- if (substream->ops->copy) {
- if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
- return err;
- } else {
- char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
- if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
- return -EFAULT;
- }
- return 0;
-}
-
-typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t size);
-
-static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
- unsigned long data,
- snd_pcm_uframes_t size,
- int nonblock,
- transfer_f transfer)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_uframes_t xfer = 0;
- snd_pcm_uframes_t offset = 0;
- int err = 0;
-
- if (size == 0)
- return 0;
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PAUSED:
- break;
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- goto _end_unlock;
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
- goto _end_unlock;
- default:
- err = -EBADFD;
- goto _end_unlock;
- }
-
- runtime->twake = runtime->control->avail_min ? : 1;
- while (size > 0) {
- snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
- snd_pcm_uframes_t avail;
- snd_pcm_uframes_t cont;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- snd_pcm_update_hw_ptr(substream);
- avail = snd_pcm_playback_avail(runtime);
- if (!avail) {
- if (nonblock) {
- err = -EAGAIN;
- goto _end_unlock;
- }
- runtime->twake = min_t(snd_pcm_uframes_t, size,
- runtime->control->avail_min ? : 1);
- err = wait_for_avail(substream, &avail);
- if (err < 0)
- goto _end_unlock;
- }
- frames = size > avail ? avail : size;
- cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
- if (frames > cont)
- frames = cont;
- if (snd_BUG_ON(!frames)) {
- runtime->twake = 0;
- snd_pcm_stream_unlock_irq(substream);
- return -EINVAL;
- }
- appl_ptr = runtime->control->appl_ptr;
- appl_ofs = appl_ptr % runtime->buffer_size;
- snd_pcm_stream_unlock_irq(substream);
- err = transfer(substream, appl_ofs, data, offset, frames);
- snd_pcm_stream_lock_irq(substream);
- if (err < 0)
- goto _end_unlock;
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- goto _end_unlock;
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
- goto _end_unlock;
- default:
- break;
- }
- appl_ptr += frames;
- if (appl_ptr >= runtime->boundary)
- appl_ptr -= runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- if (substream->ops->ack)
- substream->ops->ack(substream);
-
- offset += frames;
- size -= frames;
- xfer += frames;
- if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
- snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
- err = snd_pcm_start(substream);
- if (err < 0)
- goto _end_unlock;
- }
- }
- _end_unlock:
- runtime->twake = 0;
- if (xfer > 0 && err >= 0)
- snd_pcm_update_state(substream, runtime);
- snd_pcm_stream_unlock_irq(substream);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
-}
-
-/* sanity-check for read/write methods */
-static int pcm_sanity_check(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area))
- return -EINVAL;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- return 0;
-}
-
-snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size)
-{
- struct snd_pcm_runtime *runtime;
- int nonblock;
- int err;
-
- err = pcm_sanity_check(substream);
- if (err < 0)
- return err;
- runtime = substream->runtime;
- nonblock = !!(substream->f_flags & O_NONBLOCK);
-
- if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
- runtime->channels > 1)
- return -EINVAL;
- return snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock,
- snd_pcm_lib_write_transfer);
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_write);
-
-static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- void __user **bufs = (void __user **)data;
- int channels = runtime->channels;
- int c;
- if (substream->ops->copy) {
- if (snd_BUG_ON(!substream->ops->silence))
- return -EINVAL;
- for (c = 0; c < channels; ++c, ++bufs) {
- if (*bufs == NULL) {
- if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0)
- return err;
- } else {
- char __user *buf = *bufs + samples_to_bytes(runtime, off);
- if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
- return err;
- }
- }
- } else {
- /* default transfer behaviour */
- size_t dma_csize = runtime->dma_bytes / channels;
- for (c = 0; c < channels; ++c, ++bufs) {
- char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
- if (*bufs == NULL) {
- snd_pcm_format_set_silence(runtime->format, hwbuf, frames);
- } else {
- char __user *buf = *bufs + samples_to_bytes(runtime, off);
- if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)))
- return -EFAULT;
- }
- }
- }
- return 0;
-}
-
-snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
- void __user **bufs,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime;
- int nonblock;
- int err;
-
- err = pcm_sanity_check(substream);
- if (err < 0)
- return err;
- runtime = substream->runtime;
- nonblock = !!(substream->f_flags & O_NONBLOCK);
-
- if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
- return -EINVAL;
- return snd_pcm_lib_write1(substream, (unsigned long)bufs, frames,
- nonblock, snd_pcm_lib_writev_transfer);
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_writev);
-
-static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
- if (substream->ops->copy) {
- if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
- return err;
- } else {
- char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
- if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
- return -EFAULT;
- }
- return 0;
-}
-
-static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
- unsigned long data,
- snd_pcm_uframes_t size,
- int nonblock,
- transfer_f transfer)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_uframes_t xfer = 0;
- snd_pcm_uframes_t offset = 0;
- int err = 0;
-
- if (size == 0)
- return 0;
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- if (size >= runtime->start_threshold) {
- err = snd_pcm_start(substream);
- if (err < 0)
- goto _end_unlock;
- }
- break;
- case SNDRV_PCM_STATE_DRAINING:
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PAUSED:
- break;
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- goto _end_unlock;
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
- goto _end_unlock;
- default:
- err = -EBADFD;
- goto _end_unlock;
- }
-
- runtime->twake = runtime->control->avail_min ? : 1;
- while (size > 0) {
- snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
- snd_pcm_uframes_t avail;
- snd_pcm_uframes_t cont;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- snd_pcm_update_hw_ptr(substream);
- avail = snd_pcm_capture_avail(runtime);
- if (!avail) {
- if (runtime->status->state ==
- SNDRV_PCM_STATE_DRAINING) {
- snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
- goto _end_unlock;
- }
- if (nonblock) {
- err = -EAGAIN;
- goto _end_unlock;
- }
- runtime->twake = min_t(snd_pcm_uframes_t, size,
- runtime->control->avail_min ? : 1);
- err = wait_for_avail(substream, &avail);
- if (err < 0)
- goto _end_unlock;
- if (!avail)
- continue; /* draining */
- }
- frames = size > avail ? avail : size;
- cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
- if (frames > cont)
- frames = cont;
- if (snd_BUG_ON(!frames)) {
- runtime->twake = 0;
- snd_pcm_stream_unlock_irq(substream);
- return -EINVAL;
- }
- appl_ptr = runtime->control->appl_ptr;
- appl_ofs = appl_ptr % runtime->buffer_size;
- snd_pcm_stream_unlock_irq(substream);
- err = transfer(substream, appl_ofs, data, offset, frames);
- snd_pcm_stream_lock_irq(substream);
- if (err < 0)
- goto _end_unlock;
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- goto _end_unlock;
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
- goto _end_unlock;
- default:
- break;
- }
- appl_ptr += frames;
- if (appl_ptr >= runtime->boundary)
- appl_ptr -= runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- if (substream->ops->ack)
- substream->ops->ack(substream);
-
- offset += frames;
- size -= frames;
- xfer += frames;
- }
- _end_unlock:
- runtime->twake = 0;
- if (xfer > 0 && err >= 0)
- snd_pcm_update_state(substream, runtime);
- snd_pcm_stream_unlock_irq(substream);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
-}
-
-snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size)
-{
- struct snd_pcm_runtime *runtime;
- int nonblock;
- int err;
-
- err = pcm_sanity_check(substream);
- if (err < 0)
- return err;
- runtime = substream->runtime;
- nonblock = !!(substream->f_flags & O_NONBLOCK);
- if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
- return -EINVAL;
- return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_read);
-
-static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- void __user **bufs = (void __user **)data;
- int channels = runtime->channels;
- int c;
- if (substream->ops->copy) {
- for (c = 0; c < channels; ++c, ++bufs) {
- char __user *buf;
- if (*bufs == NULL)
- continue;
- buf = *bufs + samples_to_bytes(runtime, off);
- if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
- return err;
- }
- } else {
- snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
- for (c = 0; c < channels; ++c, ++bufs) {
- char *hwbuf;
- char __user *buf;
- if (*bufs == NULL)
- continue;
-
- hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
- buf = *bufs + samples_to_bytes(runtime, off);
- if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames)))
- return -EFAULT;
- }
- }
- return 0;
-}
-
-snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
- void __user **bufs,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime;
- int nonblock;
- int err;
-
- err = pcm_sanity_check(substream);
- if (err < 0)
- return err;
- runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
-
- nonblock = !!(substream->f_flags & O_NONBLOCK);
- if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
- return -EINVAL;
- return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_readv);
diff --git a/ANDROID_3.4.5/sound/core/pcm_memory.c b/ANDROID_3.4.5/sound/core/pcm_memory.c
deleted file mode 100644
index 95713136..00000000
--- a/ANDROID_3.4.5/sound/core/pcm_memory.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <asm/io.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/moduleparam.h>
-#include <linux/vmalloc.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/info.h>
-#include <sound/initval.h>
-
-static int preallocate_dma = 1;
-module_param(preallocate_dma, int, 0444);
-MODULE_PARM_DESC(preallocate_dma, "Preallocate DMA memory when the PCM devices are initialized.");
-
-static int maximum_substreams = 4;
-module_param(maximum_substreams, int, 0444);
-MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA memory.");
-
-static const size_t snd_minimum_buffer = 16384;
-
-
-/*
- * try to allocate as the large pages as possible.
- * stores the resultant memory size in *res_size.
- *
- * the minimum size is snd_minimum_buffer. it should be power of 2.
- */
-static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
-{
- struct snd_dma_buffer *dmab = &substream->dma_buffer;
- int err;
-
- /* already reserved? */
- if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) {
- if (dmab->bytes >= size)
- return 0; /* yes */
- /* no, free the reserved block */
- snd_dma_free_pages(dmab);
- dmab->bytes = 0;
- }
-
- do {
- if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
- size, dmab)) < 0) {
- if (err != -ENOMEM)
- return err; /* fatal error */
- } else
- return 0;
- size >>= 1;
- } while (size >= snd_minimum_buffer);
- dmab->bytes = 0; /* tell error */
- return 0;
-}
-
-/*
- * release the preallocated buffer if not yet done.
- */
-static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream)
-{
- if (substream->dma_buffer.area == NULL)
- return;
- if (substream->dma_buf_id)
- snd_dma_reserve_buf(&substream->dma_buffer, substream->dma_buf_id);
- else
- snd_dma_free_pages(&substream->dma_buffer);
- substream->dma_buffer.area = NULL;
-}
-
-/**
- * snd_pcm_lib_preallocate_free - release the preallocated buffer of the specified substream.
- * @substream: the pcm substream instance
- *
- * Releases the pre-allocated buffer of the given substream.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
-{
- snd_pcm_lib_preallocate_dma_free(substream);
-#ifdef CONFIG_SND_VERBOSE_PROCFS
- snd_info_free_entry(substream->proc_prealloc_max_entry);
- substream->proc_prealloc_max_entry = NULL;
- snd_info_free_entry(substream->proc_prealloc_entry);
- substream->proc_prealloc_entry = NULL;
-#endif
- return 0;
-}
-
-/**
- * snd_pcm_lib_preallocate_free_for_all - release all pre-allocated buffers on the pcm
- * @pcm: the pcm instance
- *
- * Releases all the pre-allocated buffers on the given pcm.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- int stream;
-
- for (stream = 0; stream < 2; stream++)
- for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
- snd_pcm_lib_preallocate_free(substream);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
-
-#ifdef CONFIG_SND_VERBOSE_PROCFS
-/*
- * read callback for prealloc proc file
- *
- * prints the current allocated size in kB.
- */
-static void snd_pcm_lib_preallocate_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_substream *substream = entry->private_data;
- snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_buffer.bytes / 1024);
-}
-
-/*
- * read callback for prealloc_max proc file
- *
- * prints the maximum allowed size in kB.
- */
-static void snd_pcm_lib_preallocate_max_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_substream *substream = entry->private_data;
- snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_max / 1024);
-}
-
-/*
- * write callback for prealloc proc file
- *
- * accepts the preallocation size in kB.
- */
-static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_pcm_substream *substream = entry->private_data;
- char line[64], str[64];
- size_t size;
- struct snd_dma_buffer new_dmab;
-
- if (substream->runtime) {
- buffer->error = -EBUSY;
- return;
- }
- if (!snd_info_get_line(buffer, line, sizeof(line))) {
- snd_info_get_str(str, line, sizeof(str));
- size = simple_strtoul(str, NULL, 10) * 1024;
- if ((size != 0 && size < 8192) || size > substream->dma_max) {
- buffer->error = -EINVAL;
- return;
- }
- if (substream->dma_buffer.bytes == size)
- return;
- memset(&new_dmab, 0, sizeof(new_dmab));
- new_dmab.dev = substream->dma_buffer.dev;
- if (size > 0) {
- if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
- substream->dma_buffer.dev.dev,
- size, &new_dmab) < 0) {
- buffer->error = -ENOMEM;
- return;
- }
- substream->buffer_bytes_max = size;
- } else {
- substream->buffer_bytes_max = UINT_MAX;
- }
- if (substream->dma_buffer.area)
- snd_dma_free_pages(&substream->dma_buffer);
- substream->dma_buffer = new_dmab;
- } else {
- buffer->error = -EINVAL;
- }
-}
-
-static inline void preallocate_info_init(struct snd_pcm_substream *substream)
-{
- struct snd_info_entry *entry;
-
- if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
- entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
- entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
- entry->mode |= S_IWUSR;
- entry->private_data = substream;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_prealloc_entry = entry;
- if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max", substream->proc_root)) != NULL) {
- entry->c.text.read = snd_pcm_lib_preallocate_max_proc_read;
- entry->private_data = substream;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- substream->proc_prealloc_max_entry = entry;
-}
-
-#else /* !CONFIG_SND_VERBOSE_PROCFS */
-#define preallocate_info_init(s)
-#endif /* CONFIG_SND_VERBOSE_PROCFS */
-
-/*
- * pre-allocate the buffer and create a proc file for the substream
- */
-static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
- size_t size, size_t max)
-{
-
- if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
- preallocate_pcm_pages(substream, size);
-
- if (substream->dma_buffer.bytes > 0)
- substream->buffer_bytes_max = substream->dma_buffer.bytes;
- substream->dma_max = max;
- preallocate_info_init(substream);
- return 0;
-}
-
-
-/**
- * snd_pcm_lib_preallocate_pages - pre-allocation for the given DMA type
- * @substream: the pcm substream instance
- * @type: DMA type (SNDRV_DMA_TYPE_*)
- * @data: DMA type dependent data
- * @size: the requested pre-allocation size in bytes
- * @max: the max. allowed pre-allocation size
- *
- * Do pre-allocation for the given DMA buffer type.
- *
- * When substream->dma_buf_id is set, the function tries to look for
- * the reserved buffer, and the buffer is not freed but reserved at
- * destruction time. The dma_buf_id must be unique for all systems
- * (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
- int type, struct device *data,
- size_t size, size_t max)
-{
- substream->dma_buffer.dev.type = type;
- substream->dma_buffer.dev.dev = data;
- return snd_pcm_lib_preallocate_pages1(substream, size, max);
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
-
-/**
- * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continuous memory type (all substreams)
- * @pcm: the pcm instance
- * @type: DMA type (SNDRV_DMA_TYPE_*)
- * @data: DMA type dependent data
- * @size: the requested pre-allocation size in bytes
- * @max: the max. allowed pre-allocation size
- *
- * Do pre-allocation to all substreams of the given pcm for the
- * specified DMA type.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
- int type, void *data,
- size_t size, size_t max)
-{
- struct snd_pcm_substream *substream;
- int stream, err;
-
- for (stream = 0; stream < 2; stream++)
- for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
- if ((err = snd_pcm_lib_preallocate_pages(substream, type, data, size, max)) < 0)
- return err;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
-
-#ifdef CONFIG_SND_DMA_SGBUF
-/**
- * snd_pcm_sgbuf_ops_page - get the page struct at the given offset
- * @substream: the pcm substream instance
- * @offset: the buffer offset
- *
- * Returns the page struct at the given buffer offset.
- * Used as the page callback of PCM ops.
- */
-struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset)
-{
- struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
-
- unsigned int idx = offset >> PAGE_SHIFT;
- if (idx >= (unsigned int)sgbuf->pages)
- return NULL;
- return sgbuf->page_table[idx];
-}
-
-EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
-
-/*
- * compute the max chunk size with continuous pages on sg-buffer
- */
-unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
- unsigned int ofs, unsigned int size)
-{
- struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
- unsigned int start, end, pg;
-
- start = ofs >> PAGE_SHIFT;
- end = (ofs + size - 1) >> PAGE_SHIFT;
- /* check page continuity */
- pg = sg->table[start].addr >> PAGE_SHIFT;
- for (;;) {
- start++;
- if (start > end)
- break;
- pg++;
- if ((sg->table[start].addr >> PAGE_SHIFT) != pg)
- return (start << PAGE_SHIFT) - ofs;
- }
- /* ok, all on continuous pages */
- return size;
-}
-EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size);
-#endif /* CONFIG_SND_DMA_SGBUF */
-
-/**
- * snd_pcm_lib_malloc_pages - allocate the DMA buffer
- * @substream: the substream to allocate the DMA buffer to
- * @size: the requested buffer size in bytes
- *
- * Allocates the DMA buffer on the BUS type given earlier to
- * snd_pcm_lib_preallocate_xxx_pages().
- *
- * Returns 1 if the buffer is changed, 0 if not changed, or a negative
- * code on failure.
- */
-int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
-{
- struct snd_pcm_runtime *runtime;
- struct snd_dma_buffer *dmab = NULL;
-
- if (PCM_RUNTIME_CHECK(substream))
- return -EINVAL;
- if (snd_BUG_ON(substream->dma_buffer.dev.type ==
- SNDRV_DMA_TYPE_UNKNOWN))
- return -EINVAL;
- runtime = substream->runtime;
-
- if (runtime->dma_buffer_p) {
- /* perphaps, we might free the large DMA memory region
- to save some space here, but the actual solution
- costs us less time */
- if (runtime->dma_buffer_p->bytes >= size) {
- runtime->dma_bytes = size;
- return 0; /* ok, do not change */
- }
- snd_pcm_lib_free_pages(substream);
- }
- if (substream->dma_buffer.area != NULL &&
- substream->dma_buffer.bytes >= size) {
- dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
- } else {
- dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
- if (! dmab)
- return -ENOMEM;
- dmab->dev = substream->dma_buffer.dev;
- if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
- substream->dma_buffer.dev.dev,
- size, dmab) < 0) {
- kfree(dmab);
- return -ENOMEM;
- }
- }
- snd_pcm_set_runtime_buffer(substream, dmab);
- runtime->dma_bytes = size;
- return 1; /* area was changed */
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
-
-/**
- * snd_pcm_lib_free_pages - release the allocated DMA buffer.
- * @substream: the substream to release the DMA buffer
- *
- * Releases the DMA buffer allocated via snd_pcm_lib_malloc_pages().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
-
- if (PCM_RUNTIME_CHECK(substream))
- return -EINVAL;
- runtime = substream->runtime;
- if (runtime->dma_area == NULL)
- return 0;
- if (runtime->dma_buffer_p != &substream->dma_buffer) {
- /* it's a newly allocated buffer. release it now. */
- snd_dma_free_pages(runtime->dma_buffer_p);
- kfree(runtime->dma_buffer_p);
- }
- snd_pcm_set_runtime_buffer(substream, NULL);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_free_pages);
-
-int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
- size_t size, gfp_t gfp_flags)
-{
- struct snd_pcm_runtime *runtime;
-
- if (PCM_RUNTIME_CHECK(substream))
- return -EINVAL;
- runtime = substream->runtime;
- if (runtime->dma_area) {
- if (runtime->dma_bytes >= size)
- return 0; /* already large enough */
- vfree(runtime->dma_area);
- }
- runtime->dma_area = __vmalloc(size, gfp_flags, PAGE_KERNEL);
- if (!runtime->dma_area)
- return -ENOMEM;
- runtime->dma_bytes = size;
- return 1;
-}
-EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer);
-
-/**
- * snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer
- * @substream: the substream with a buffer allocated by
- * snd_pcm_lib_alloc_vmalloc_buffer()
- */
-int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
-
- if (PCM_RUNTIME_CHECK(substream))
- return -EINVAL;
- runtime = substream->runtime;
- vfree(runtime->dma_area);
- runtime->dma_area = NULL;
- return 0;
-}
-EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer);
-
-/**
- * snd_pcm_lib_get_vmalloc_page - map vmalloc buffer offset to page struct
- * @substream: the substream with a buffer allocated by
- * snd_pcm_lib_alloc_vmalloc_buffer()
- * @offset: offset in the buffer
- *
- * This function is to be used as the page callback in the PCM ops.
- */
-struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
- unsigned long offset)
-{
- return vmalloc_to_page(substream->runtime->dma_area + offset);
-}
-EXPORT_SYMBOL(snd_pcm_lib_get_vmalloc_page);
diff --git a/ANDROID_3.4.5/sound/core/pcm_misc.c b/ANDROID_3.4.5/sound/core/pcm_misc.c
deleted file mode 100644
index 9c9eff9a..00000000
--- a/ANDROID_3.4.5/sound/core/pcm_misc.c
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * PCM Interface - misc routines
- * Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/time.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#define SND_PCM_FORMAT_UNKNOWN (-1)
-
-/* NOTE: "signed" prefix must be given below since the default char is
- * unsigned on some architectures!
- */
-struct pcm_format_data {
- unsigned char width; /* bit width */
- unsigned char phys; /* physical bit width */
- signed char le; /* 0 = big-endian, 1 = little-endian, -1 = others */
- signed char signd; /* 0 = unsigned, 1 = signed, -1 = others */
- unsigned char silence[8]; /* silence data to fill */
-};
-
-/* we do lots of calculations on snd_pcm_format_t; shut up sparse */
-#define INT __force int
-
-static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
- [SNDRV_PCM_FORMAT_S8] = {
- .width = 8, .phys = 8, .le = -1, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_U8] = {
- .width = 8, .phys = 8, .le = -1, .signd = 0,
- .silence = { 0x80 },
- },
- [SNDRV_PCM_FORMAT_S16_LE] = {
- .width = 16, .phys = 16, .le = 1, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_S16_BE] = {
- .width = 16, .phys = 16, .le = 0, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_U16_LE] = {
- .width = 16, .phys = 16, .le = 1, .signd = 0,
- .silence = { 0x00, 0x80 },
- },
- [SNDRV_PCM_FORMAT_U16_BE] = {
- .width = 16, .phys = 16, .le = 0, .signd = 0,
- .silence = { 0x80, 0x00 },
- },
- [SNDRV_PCM_FORMAT_S24_LE] = {
- .width = 24, .phys = 32, .le = 1, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_S24_BE] = {
- .width = 24, .phys = 32, .le = 0, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_U24_LE] = {
- .width = 24, .phys = 32, .le = 1, .signd = 0,
- .silence = { 0x00, 0x00, 0x80 },
- },
- [SNDRV_PCM_FORMAT_U24_BE] = {
- .width = 24, .phys = 32, .le = 0, .signd = 0,
- .silence = { 0x00, 0x80, 0x00, 0x00 },
- },
- [SNDRV_PCM_FORMAT_S32_LE] = {
- .width = 32, .phys = 32, .le = 1, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_S32_BE] = {
- .width = 32, .phys = 32, .le = 0, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_U32_LE] = {
- .width = 32, .phys = 32, .le = 1, .signd = 0,
- .silence = { 0x00, 0x00, 0x00, 0x80 },
- },
- [SNDRV_PCM_FORMAT_U32_BE] = {
- .width = 32, .phys = 32, .le = 0, .signd = 0,
- .silence = { 0x80, 0x00, 0x00, 0x00 },
- },
- [SNDRV_PCM_FORMAT_FLOAT_LE] = {
- .width = 32, .phys = 32, .le = 1, .signd = -1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_FLOAT_BE] = {
- .width = 32, .phys = 32, .le = 0, .signd = -1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_FLOAT64_LE] = {
- .width = 64, .phys = 64, .le = 1, .signd = -1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_FLOAT64_BE] = {
- .width = 64, .phys = 64, .le = 0, .signd = -1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE] = {
- .width = 32, .phys = 32, .le = 1, .signd = -1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE] = {
- .width = 32, .phys = 32, .le = 0, .signd = -1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_MU_LAW] = {
- .width = 8, .phys = 8, .le = -1, .signd = -1,
- .silence = { 0x7f },
- },
- [SNDRV_PCM_FORMAT_A_LAW] = {
- .width = 8, .phys = 8, .le = -1, .signd = -1,
- .silence = { 0x55 },
- },
- [SNDRV_PCM_FORMAT_IMA_ADPCM] = {
- .width = 4, .phys = 4, .le = -1, .signd = -1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_G723_24] = {
- .width = 3, .phys = 3, .le = -1, .signd = -1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_G723_40] = {
- .width = 5, .phys = 5, .le = -1, .signd = -1,
- .silence = {},
- },
- /* FIXME: the following three formats are not defined properly yet */
- [SNDRV_PCM_FORMAT_MPEG] = {
- .le = -1, .signd = -1,
- },
- [SNDRV_PCM_FORMAT_GSM] = {
- .le = -1, .signd = -1,
- },
- [SNDRV_PCM_FORMAT_SPECIAL] = {
- .le = -1, .signd = -1,
- },
- [SNDRV_PCM_FORMAT_S24_3LE] = {
- .width = 24, .phys = 24, .le = 1, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_S24_3BE] = {
- .width = 24, .phys = 24, .le = 0, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_U24_3LE] = {
- .width = 24, .phys = 24, .le = 1, .signd = 0,
- .silence = { 0x00, 0x00, 0x80 },
- },
- [SNDRV_PCM_FORMAT_U24_3BE] = {
- .width = 24, .phys = 24, .le = 0, .signd = 0,
- .silence = { 0x80, 0x00, 0x00 },
- },
- [SNDRV_PCM_FORMAT_S20_3LE] = {
- .width = 20, .phys = 24, .le = 1, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_S20_3BE] = {
- .width = 20, .phys = 24, .le = 0, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_U20_3LE] = {
- .width = 20, .phys = 24, .le = 1, .signd = 0,
- .silence = { 0x00, 0x00, 0x08 },
- },
- [SNDRV_PCM_FORMAT_U20_3BE] = {
- .width = 20, .phys = 24, .le = 0, .signd = 0,
- .silence = { 0x08, 0x00, 0x00 },
- },
- [SNDRV_PCM_FORMAT_S18_3LE] = {
- .width = 18, .phys = 24, .le = 1, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_S18_3BE] = {
- .width = 18, .phys = 24, .le = 0, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_U18_3LE] = {
- .width = 18, .phys = 24, .le = 1, .signd = 0,
- .silence = { 0x00, 0x00, 0x02 },
- },
- [SNDRV_PCM_FORMAT_U18_3BE] = {
- .width = 18, .phys = 24, .le = 0, .signd = 0,
- .silence = { 0x02, 0x00, 0x00 },
- },
- [SNDRV_PCM_FORMAT_G723_24_1B] = {
- .width = 3, .phys = 8, .le = -1, .signd = -1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_G723_40_1B] = {
- .width = 5, .phys = 8, .le = -1, .signd = -1,
- .silence = {},
- },
-};
-
-
-/**
- * snd_pcm_format_signed - Check the PCM format is signed linear
- * @format: the format to check
- *
- * Returns 1 if the given PCM format is signed linear, 0 if unsigned
- * linear, and a negative error code for non-linear formats.
- */
-int snd_pcm_format_signed(snd_pcm_format_t format)
-{
- int val;
- if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
- return -EINVAL;
- if ((val = pcm_formats[(INT)format].signd) < 0)
- return -EINVAL;
- return val;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_signed);
-
-/**
- * snd_pcm_format_unsigned - Check the PCM format is unsigned linear
- * @format: the format to check
- *
- * Returns 1 if the given PCM format is unsigned linear, 0 if signed
- * linear, and a negative error code for non-linear formats.
- */
-int snd_pcm_format_unsigned(snd_pcm_format_t format)
-{
- int val;
-
- val = snd_pcm_format_signed(format);
- if (val < 0)
- return val;
- return !val;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_unsigned);
-
-/**
- * snd_pcm_format_linear - Check the PCM format is linear
- * @format: the format to check
- *
- * Returns 1 if the given PCM format is linear, 0 if not.
- */
-int snd_pcm_format_linear(snd_pcm_format_t format)
-{
- return snd_pcm_format_signed(format) >= 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_linear);
-
-/**
- * snd_pcm_format_little_endian - Check the PCM format is little-endian
- * @format: the format to check
- *
- * Returns 1 if the given PCM format is little-endian, 0 if
- * big-endian, or a negative error code if endian not specified.
- */
-int snd_pcm_format_little_endian(snd_pcm_format_t format)
-{
- int val;
- if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
- return -EINVAL;
- if ((val = pcm_formats[(INT)format].le) < 0)
- return -EINVAL;
- return val;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_little_endian);
-
-/**
- * snd_pcm_format_big_endian - Check the PCM format is big-endian
- * @format: the format to check
- *
- * Returns 1 if the given PCM format is big-endian, 0 if
- * little-endian, or a negative error code if endian not specified.
- */
-int snd_pcm_format_big_endian(snd_pcm_format_t format)
-{
- int val;
-
- val = snd_pcm_format_little_endian(format);
- if (val < 0)
- return val;
- return !val;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_big_endian);
-
-/**
- * snd_pcm_format_width - return the bit-width of the format
- * @format: the format to check
- *
- * Returns the bit-width of the format, or a negative error code
- * if unknown format.
- */
-int snd_pcm_format_width(snd_pcm_format_t format)
-{
- int val;
- if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
- return -EINVAL;
- if ((val = pcm_formats[(INT)format].width) == 0)
- return -EINVAL;
- return val;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_width);
-
-/**
- * snd_pcm_format_physical_width - return the physical bit-width of the format
- * @format: the format to check
- *
- * Returns the physical bit-width of the format, or a negative error code
- * if unknown format.
- */
-int snd_pcm_format_physical_width(snd_pcm_format_t format)
-{
- int val;
- if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
- return -EINVAL;
- if ((val = pcm_formats[(INT)format].phys) == 0)
- return -EINVAL;
- return val;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_physical_width);
-
-/**
- * snd_pcm_format_size - return the byte size of samples on the given format
- * @format: the format to check
- * @samples: sampling rate
- *
- * Returns the byte size of the given samples for the format, or a
- * negative error code if unknown format.
- */
-ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
-{
- int phys_width = snd_pcm_format_physical_width(format);
- if (phys_width < 0)
- return -EINVAL;
- return samples * phys_width / 8;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_size);
-
-/**
- * snd_pcm_format_silence_64 - return the silent data in 8 bytes array
- * @format: the format to check
- *
- * Returns the format pattern to fill or NULL if error.
- */
-const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
-{
- if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
- return NULL;
- if (! pcm_formats[(INT)format].phys)
- return NULL;
- return pcm_formats[(INT)format].silence;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_silence_64);
-
-/**
- * snd_pcm_format_set_silence - set the silence data on the buffer
- * @format: the PCM format
- * @data: the buffer pointer
- * @samples: the number of samples to set silence
- *
- * Sets the silence data on the buffer for the given samples.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
-{
- int width;
- unsigned char *dst, *pat;
-
- if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
- return -EINVAL;
- if (samples == 0)
- return 0;
- width = pcm_formats[(INT)format].phys; /* physical width */
- pat = pcm_formats[(INT)format].silence;
- if (! width)
- return -EINVAL;
- /* signed or 1 byte data */
- if (pcm_formats[(INT)format].signd == 1 || width <= 8) {
- unsigned int bytes = samples * width / 8;
- memset(data, *pat, bytes);
- return 0;
- }
- /* non-zero samples, fill using a loop */
- width /= 8;
- dst = data;
-#if 0
- while (samples--) {
- memcpy(dst, pat, width);
- dst += width;
- }
-#else
- /* a bit optimization for constant width */
- switch (width) {
- case 2:
- while (samples--) {
- memcpy(dst, pat, 2);
- dst += 2;
- }
- break;
- case 3:
- while (samples--) {
- memcpy(dst, pat, 3);
- dst += 3;
- }
- break;
- case 4:
- while (samples--) {
- memcpy(dst, pat, 4);
- dst += 4;
- }
- break;
- case 8:
- while (samples--) {
- memcpy(dst, pat, 8);
- dst += 8;
- }
- break;
- }
-#endif
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_format_set_silence);
-
-/**
- * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields
- * @runtime: the runtime instance
- *
- * Determines the rate_min and rate_max fields from the rates bits of
- * the given runtime->hw.
- *
- * Returns zero if successful.
- */
-int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
-{
- int i;
- for (i = 0; i < (int)snd_pcm_known_rates.count; i++) {
- if (runtime->hw.rates & (1 << i)) {
- runtime->hw.rate_min = snd_pcm_known_rates.list[i];
- break;
- }
- }
- for (i = (int)snd_pcm_known_rates.count - 1; i >= 0; i--) {
- if (runtime->hw.rates & (1 << i)) {
- runtime->hw.rate_max = snd_pcm_known_rates.list[i];
- break;
- }
- }
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
-
-/**
- * snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit
- * @rate: the sample rate to convert
- *
- * Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or
- * SNDRV_PCM_RATE_KNOT for an unknown rate.
- */
-unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate)
-{
- unsigned int i;
-
- for (i = 0; i < snd_pcm_known_rates.count; i++)
- if (snd_pcm_known_rates.list[i] == rate)
- return 1u << i;
- return SNDRV_PCM_RATE_KNOT;
-}
-EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit);
diff --git a/ANDROID_3.4.5/sound/core/pcm_native.c b/ANDROID_3.4.5/sound/core/pcm_native.c
deleted file mode 100644
index d535b341..00000000
--- a/ANDROID_3.4.5/sound/core/pcm_native.c
+++ /dev/null
@@ -1,3492 +0,0 @@
-/*
- * Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/file.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/pm_qos.h>
-#include <linux/uio.h>
-#include <linux/dma-mapping.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/info.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/timer.h>
-#include <sound/minors.h>
-#include <asm/io.h>
-#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
-#include <dma-coherence.h>
-#endif
-
-/*
- * Compatibility
- */
-
-struct snd_pcm_hw_params_old {
- unsigned int flags;
- unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
- SNDRV_PCM_HW_PARAM_ACCESS + 1];
- struct snd_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
- unsigned int rmask;
- unsigned int cmask;
- unsigned int info;
- unsigned int msbits;
- unsigned int rate_num;
- unsigned int rate_den;
- snd_pcm_uframes_t fifo_size;
- unsigned char reserved[64];
-};
-
-#ifdef CONFIG_SND_SUPPORT_OLD_API
-#define SNDRV_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct snd_pcm_hw_params_old)
-#define SNDRV_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct snd_pcm_hw_params_old)
-
-static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params_old __user * _oparams);
-static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params_old __user * _oparams);
-#endif
-static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
-
-/*
- *
- */
-
-DEFINE_RWLOCK(snd_pcm_link_rwlock);
-EXPORT_SYMBOL(snd_pcm_link_rwlock);
-
-static DECLARE_RWSEM(snd_pcm_link_rwsem);
-
-static inline mm_segment_t snd_enter_user(void)
-{
- mm_segment_t fs = get_fs();
- set_fs(get_ds());
- return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
- set_fs(fs);
-}
-
-
-
-int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
-{
- struct snd_pcm_runtime *runtime;
- struct snd_pcm *pcm = substream->pcm;
- struct snd_pcm_str *pstr = substream->pstr;
-
- memset(info, 0, sizeof(*info));
- info->card = pcm->card->number;
- info->device = pcm->device;
- info->stream = substream->stream;
- info->subdevice = substream->number;
- strlcpy(info->id, pcm->id, sizeof(info->id));
- strlcpy(info->name, pcm->name, sizeof(info->name));
- info->dev_class = pcm->dev_class;
- info->dev_subclass = pcm->dev_subclass;
- info->subdevices_count = pstr->substream_count;
- info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
- strlcpy(info->subname, substream->name, sizeof(info->subname));
- runtime = substream->runtime;
- /* AB: FIXME!!! This is definitely nonsense */
- if (runtime) {
- info->sync = runtime->sync;
- substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
- }
- return 0;
-}
-
-int snd_pcm_info_user(struct snd_pcm_substream *substream,
- struct snd_pcm_info __user * _info)
-{
- struct snd_pcm_info *info;
- int err;
-
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info)
- return -ENOMEM;
- err = snd_pcm_info(substream, info);
- if (err >= 0) {
- if (copy_to_user(_info, info, sizeof(*info)))
- err = -EFAULT;
- }
- kfree(info);
- return err;
-}
-
-#undef RULES_DEBUG
-
-#ifdef RULES_DEBUG
-#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v
-static const char * const snd_pcm_hw_param_names[] = {
- HW_PARAM(ACCESS),
- HW_PARAM(FORMAT),
- HW_PARAM(SUBFORMAT),
- HW_PARAM(SAMPLE_BITS),
- HW_PARAM(FRAME_BITS),
- HW_PARAM(CHANNELS),
- HW_PARAM(RATE),
- HW_PARAM(PERIOD_TIME),
- HW_PARAM(PERIOD_SIZE),
- HW_PARAM(PERIOD_BYTES),
- HW_PARAM(PERIODS),
- HW_PARAM(BUFFER_TIME),
- HW_PARAM(BUFFER_SIZE),
- HW_PARAM(BUFFER_BYTES),
- HW_PARAM(TICK_TIME),
-};
-#endif
-
-int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- unsigned int k;
- struct snd_pcm_hardware *hw;
- struct snd_interval *i = NULL;
- struct snd_mask *m = NULL;
- struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints;
- unsigned int rstamps[constrs->rules_num];
- unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
- unsigned int stamp = 2;
- int changed, again;
-
- params->info = 0;
- params->fifo_size = 0;
- if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
- params->msbits = 0;
- if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
- params->rate_num = 0;
- params->rate_den = 0;
- }
-
- for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
- m = hw_param_mask(params, k);
- if (snd_mask_empty(m))
- return -EINVAL;
- if (!(params->rmask & (1 << k)))
- continue;
-#ifdef RULES_DEBUG
- printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
- printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
-#endif
- changed = snd_mask_refine(m, constrs_mask(constrs, k));
-#ifdef RULES_DEBUG
- printk("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
-#endif
- if (changed)
- params->cmask |= 1 << k;
- if (changed < 0)
- return changed;
- }
-
- for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
- i = hw_param_interval(params, k);
- if (snd_interval_empty(i))
- return -EINVAL;
- if (!(params->rmask & (1 << k)))
- continue;
-#ifdef RULES_DEBUG
- printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
- if (i->empty)
- printk("empty");
- else
- printk("%c%u %u%c",
- i->openmin ? '(' : '[', i->min,
- i->max, i->openmax ? ')' : ']');
- printk(" -> ");
-#endif
- changed = snd_interval_refine(i, constrs_interval(constrs, k));
-#ifdef RULES_DEBUG
- if (i->empty)
- printk("empty\n");
- else
- printk("%c%u %u%c\n",
- i->openmin ? '(' : '[', i->min,
- i->max, i->openmax ? ')' : ']');
-#endif
- if (changed)
- params->cmask |= 1 << k;
- if (changed < 0)
- return changed;
- }
-
- for (k = 0; k < constrs->rules_num; k++)
- rstamps[k] = 0;
- for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
- vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
- do {
- again = 0;
- for (k = 0; k < constrs->rules_num; k++) {
- struct snd_pcm_hw_rule *r = &constrs->rules[k];
- unsigned int d;
- int doit = 0;
- if (r->cond && !(r->cond & params->flags))
- continue;
- for (d = 0; r->deps[d] >= 0; d++) {
- if (vstamps[r->deps[d]] > rstamps[k]) {
- doit = 1;
- break;
- }
- }
- if (!doit)
- continue;
-#ifdef RULES_DEBUG
- printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func);
- if (r->var >= 0) {
- printk("%s = ", snd_pcm_hw_param_names[r->var]);
- if (hw_is_mask(r->var)) {
- m = hw_param_mask(params, r->var);
- printk("%x", *m->bits);
- } else {
- i = hw_param_interval(params, r->var);
- if (i->empty)
- printk("empty");
- else
- printk("%c%u %u%c",
- i->openmin ? '(' : '[', i->min,
- i->max, i->openmax ? ')' : ']');
- }
- }
-#endif
- changed = r->func(params, r);
-#ifdef RULES_DEBUG
- if (r->var >= 0) {
- printk(" -> ");
- if (hw_is_mask(r->var))
- printk("%x", *m->bits);
- else {
- if (i->empty)
- printk("empty");
- else
- printk("%c%u %u%c",
- i->openmin ? '(' : '[', i->min,
- i->max, i->openmax ? ')' : ']');
- }
- }
- printk("\n");
-#endif
- rstamps[k] = stamp;
- if (changed && r->var >= 0) {
- params->cmask |= (1 << r->var);
- vstamps[r->var] = stamp;
- again = 1;
- }
- if (changed < 0)
- return changed;
- stamp++;
- }
- } while (again);
- if (!params->msbits) {
- i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
- if (snd_interval_single(i))
- params->msbits = snd_interval_value(i);
- }
-
- if (!params->rate_den) {
- i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
- if (snd_interval_single(i)) {
- params->rate_num = snd_interval_value(i);
- params->rate_den = 1;
- }
- }
-
- hw = &substream->runtime->hw;
- if (!params->info)
- params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES;
- if (!params->fifo_size) {
- m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
- i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- if (snd_mask_min(m) == snd_mask_max(m) &&
- snd_interval_min(i) == snd_interval_max(i)) {
- changed = substream->ops->ioctl(substream,
- SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
- if (changed < 0)
- return changed;
- }
- }
- params->rmask = 0;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_hw_refine);
-
-static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params __user * _params)
-{
- struct snd_pcm_hw_params *params;
- int err;
-
- params = memdup_user(_params, sizeof(*params));
- if (IS_ERR(params))
- return PTR_ERR(params);
-
- err = snd_pcm_hw_refine(substream, params);
- if (copy_to_user(_params, params, sizeof(*params))) {
- if (!err)
- err = -EFAULT;
- }
-
- kfree(params);
- return err;
-}
-
-static int period_to_usecs(struct snd_pcm_runtime *runtime)
-{
- int usecs;
-
- if (! runtime->rate)
- return -1; /* invalid */
-
- /* take 75% of period time as the deadline */
- usecs = (750000 / runtime->rate) * runtime->period_size;
- usecs += ((750000 % runtime->rate) * runtime->period_size) /
- runtime->rate;
-
- return usecs;
-}
-
-static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
-{
- snd_pcm_stream_lock_irq(substream);
- if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
- substream->runtime->status->state = state;
- snd_pcm_stream_unlock_irq(substream);
-}
-
-static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime;
- int err, usecs;
- unsigned int bits;
- snd_pcm_uframes_t frames;
-
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_OPEN:
- case SNDRV_PCM_STATE_SETUP:
- case SNDRV_PCM_STATE_PREPARED:
- break;
- default:
- snd_pcm_stream_unlock_irq(substream);
- return -EBADFD;
- }
- snd_pcm_stream_unlock_irq(substream);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (!substream->oss.oss)
-#endif
- if (atomic_read(&substream->mmap_count))
- return -EBADFD;
-
- params->rmask = ~0U;
- err = snd_pcm_hw_refine(substream, params);
- if (err < 0)
- goto _error;
-
- err = snd_pcm_hw_params_choose(substream, params);
- if (err < 0)
- goto _error;
-
- if (substream->ops->hw_params != NULL) {
- err = substream->ops->hw_params(substream, params);
- if (err < 0)
- goto _error;
- }
-
- runtime->access = params_access(params);
- runtime->format = params_format(params);
- runtime->subformat = params_subformat(params);
- runtime->channels = params_channels(params);
- runtime->rate = params_rate(params);
- runtime->period_size = params_period_size(params);
- runtime->periods = params_periods(params);
- runtime->buffer_size = params_buffer_size(params);
- runtime->info = params->info;
- runtime->rate_num = params->rate_num;
- runtime->rate_den = params->rate_den;
- runtime->no_period_wakeup =
- (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) &&
- (params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP);
-
- bits = snd_pcm_format_physical_width(runtime->format);
- runtime->sample_bits = bits;
- bits *= runtime->channels;
- runtime->frame_bits = bits;
- frames = 1;
- while (bits % 8 != 0) {
- bits *= 2;
- frames *= 2;
- }
- runtime->byte_align = bits / 8;
- runtime->min_align = frames;
-
- /* Default sw params */
- runtime->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
- runtime->period_step = 1;
- runtime->control->avail_min = runtime->period_size;
- runtime->start_threshold = 1;
- runtime->stop_threshold = runtime->buffer_size;
- runtime->silence_threshold = 0;
- runtime->silence_size = 0;
- runtime->boundary = runtime->buffer_size;
- while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
- runtime->boundary *= 2;
-
- snd_pcm_timer_resolution_change(substream);
- snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
-
- if (pm_qos_request_active(&substream->latency_pm_qos_req))
- pm_qos_remove_request(&substream->latency_pm_qos_req);
- if ((usecs = period_to_usecs(runtime)) >= 0)
- pm_qos_add_request(&substream->latency_pm_qos_req,
- PM_QOS_CPU_DMA_LATENCY, usecs);
- return 0;
- _error:
- /* hardware might be unusable from this time,
- so we force application to retry to set
- the correct hardware parameter settings */
- snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
- if (substream->ops->hw_free != NULL)
- substream->ops->hw_free(substream);
- return err;
-}
-
-static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params __user * _params)
-{
- struct snd_pcm_hw_params *params;
- int err;
-
- params = memdup_user(_params, sizeof(*params));
- if (IS_ERR(params))
- return PTR_ERR(params);
-
- err = snd_pcm_hw_params(substream, params);
- if (copy_to_user(_params, params, sizeof(*params))) {
- if (!err)
- err = -EFAULT;
- }
-
- kfree(params);
- return err;
-}
-
-static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
- int result = 0;
-
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_SETUP:
- case SNDRV_PCM_STATE_PREPARED:
- break;
- default:
- snd_pcm_stream_unlock_irq(substream);
- return -EBADFD;
- }
- snd_pcm_stream_unlock_irq(substream);
- if (atomic_read(&substream->mmap_count))
- return -EBADFD;
- if (substream->ops->hw_free)
- result = substream->ops->hw_free(substream);
- snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
- pm_qos_remove_request(&substream->latency_pm_qos_req);
- return result;
-}
-
-static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_sw_params *params)
-{
- struct snd_pcm_runtime *runtime;
- int err;
-
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- snd_pcm_stream_lock_irq(substream);
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
- snd_pcm_stream_unlock_irq(substream);
- return -EBADFD;
- }
- snd_pcm_stream_unlock_irq(substream);
-
- if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
- return -EINVAL;
- if (params->avail_min == 0)
- return -EINVAL;
- if (params->silence_size >= runtime->boundary) {
- if (params->silence_threshold != 0)
- return -EINVAL;
- } else {
- if (params->silence_size > params->silence_threshold)
- return -EINVAL;
- if (params->silence_threshold > runtime->buffer_size)
- return -EINVAL;
- }
- err = 0;
- snd_pcm_stream_lock_irq(substream);
- runtime->tstamp_mode = params->tstamp_mode;
- runtime->period_step = params->period_step;
- runtime->control->avail_min = params->avail_min;
- runtime->start_threshold = params->start_threshold;
- runtime->stop_threshold = params->stop_threshold;
- runtime->silence_threshold = params->silence_threshold;
- runtime->silence_size = params->silence_size;
- params->boundary = runtime->boundary;
- if (snd_pcm_running(substream)) {
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
- runtime->silence_size > 0)
- snd_pcm_playback_silence(substream, ULONG_MAX);
- err = snd_pcm_update_state(substream, runtime);
- }
- snd_pcm_stream_unlock_irq(substream);
- return err;
-}
-
-static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
- struct snd_pcm_sw_params __user * _params)
-{
- struct snd_pcm_sw_params params;
- int err;
- if (copy_from_user(&params, _params, sizeof(params)))
- return -EFAULT;
- err = snd_pcm_sw_params(substream, &params);
- if (copy_to_user(_params, &params, sizeof(params)))
- return -EFAULT;
- return err;
-}
-
-int snd_pcm_status(struct snd_pcm_substream *substream,
- struct snd_pcm_status *status)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- snd_pcm_stream_lock_irq(substream);
- status->state = runtime->status->state;
- status->suspended_state = runtime->status->suspended_state;
- if (status->state == SNDRV_PCM_STATE_OPEN)
- goto _end;
- status->trigger_tstamp = runtime->trigger_tstamp;
- if (snd_pcm_running(substream)) {
- snd_pcm_update_hw_ptr(substream);
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
- status->tstamp = runtime->status->tstamp;
- goto _tstamp_end;
- }
- }
- snd_pcm_gettime(runtime, &status->tstamp);
- _tstamp_end:
- status->appl_ptr = runtime->control->appl_ptr;
- status->hw_ptr = runtime->status->hw_ptr;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- status->avail = snd_pcm_playback_avail(runtime);
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
- runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
- status->delay = runtime->buffer_size - status->avail;
- status->delay += runtime->delay;
- } else
- status->delay = 0;
- } else {
- status->avail = snd_pcm_capture_avail(runtime);
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- status->delay = status->avail + runtime->delay;
- else
- status->delay = 0;
- }
- status->avail_max = runtime->avail_max;
- status->overrange = runtime->overrange;
- runtime->avail_max = 0;
- runtime->overrange = 0;
- _end:
- snd_pcm_stream_unlock_irq(substream);
- return 0;
-}
-
-static int snd_pcm_status_user(struct snd_pcm_substream *substream,
- struct snd_pcm_status __user * _status)
-{
- struct snd_pcm_status status;
- int res;
-
- memset(&status, 0, sizeof(status));
- res = snd_pcm_status(substream, &status);
- if (res < 0)
- return res;
- if (copy_to_user(_status, &status, sizeof(status)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
- struct snd_pcm_channel_info * info)
-{
- struct snd_pcm_runtime *runtime;
- unsigned int channel;
-
- channel = info->channel;
- runtime = substream->runtime;
- snd_pcm_stream_lock_irq(substream);
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
- snd_pcm_stream_unlock_irq(substream);
- return -EBADFD;
- }
- snd_pcm_stream_unlock_irq(substream);
- if (channel >= runtime->channels)
- return -EINVAL;
- memset(info, 0, sizeof(*info));
- info->channel = channel;
- return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info);
-}
-
-static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
- struct snd_pcm_channel_info __user * _info)
-{
- struct snd_pcm_channel_info info;
- int res;
-
- if (copy_from_user(&info, _info, sizeof(info)))
- return -EFAULT;
- res = snd_pcm_channel_info(substream, &info);
- if (res < 0)
- return res;
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->trigger_master == NULL)
- return;
- if (runtime->trigger_master == substream) {
- snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
- } else {
- snd_pcm_trigger_tstamp(runtime->trigger_master);
- runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp;
- }
- runtime->trigger_master = NULL;
-}
-
-struct action_ops {
- int (*pre_action)(struct snd_pcm_substream *substream, int state);
- int (*do_action)(struct snd_pcm_substream *substream, int state);
- void (*undo_action)(struct snd_pcm_substream *substream, int state);
- void (*post_action)(struct snd_pcm_substream *substream, int state);
-};
-
-/*
- * this functions is core for handling of linked stream
- * Note: the stream state might be changed also on failure
- * Note2: call with calling stream lock + link lock
- */
-static int snd_pcm_action_group(struct action_ops *ops,
- struct snd_pcm_substream *substream,
- int state, int do_lock)
-{
- struct snd_pcm_substream *s = NULL;
- struct snd_pcm_substream *s1;
- int res = 0;
-
- snd_pcm_group_for_each_entry(s, substream) {
- if (do_lock && s != substream)
- spin_lock_nested(&s->self_group.lock,
- SINGLE_DEPTH_NESTING);
- res = ops->pre_action(s, state);
- if (res < 0)
- goto _unlock;
- }
- snd_pcm_group_for_each_entry(s, substream) {
- res = ops->do_action(s, state);
- if (res < 0) {
- if (ops->undo_action) {
- snd_pcm_group_for_each_entry(s1, substream) {
- if (s1 == s) /* failed stream */
- break;
- ops->undo_action(s1, state);
- }
- }
- s = NULL; /* unlock all */
- goto _unlock;
- }
- }
- snd_pcm_group_for_each_entry(s, substream) {
- ops->post_action(s, state);
- }
- _unlock:
- if (do_lock) {
- /* unlock streams */
- snd_pcm_group_for_each_entry(s1, substream) {
- if (s1 != substream)
- spin_unlock(&s1->self_group.lock);
- if (s1 == s) /* end */
- break;
- }
- }
- return res;
-}
-
-/*
- * Note: call with stream lock
- */
-static int snd_pcm_action_single(struct action_ops *ops,
- struct snd_pcm_substream *substream,
- int state)
-{
- int res;
-
- res = ops->pre_action(substream, state);
- if (res < 0)
- return res;
- res = ops->do_action(substream, state);
- if (res == 0)
- ops->post_action(substream, state);
- else if (ops->undo_action)
- ops->undo_action(substream, state);
- return res;
-}
-
-/*
- * Note: call with stream lock
- */
-static int snd_pcm_action(struct action_ops *ops,
- struct snd_pcm_substream *substream,
- int state)
-{
- int res;
-
- if (snd_pcm_stream_linked(substream)) {
- if (!spin_trylock(&substream->group->lock)) {
- spin_unlock(&substream->self_group.lock);
- spin_lock(&substream->group->lock);
- spin_lock(&substream->self_group.lock);
- }
- res = snd_pcm_action_group(ops, substream, state, 1);
- spin_unlock(&substream->group->lock);
- } else {
- res = snd_pcm_action_single(ops, substream, state);
- }
- return res;
-}
-
-/*
- * Note: don't use any locks before
- */
-static int snd_pcm_action_lock_irq(struct action_ops *ops,
- struct snd_pcm_substream *substream,
- int state)
-{
- int res;
-
- read_lock_irq(&snd_pcm_link_rwlock);
- if (snd_pcm_stream_linked(substream)) {
- spin_lock(&substream->group->lock);
- spin_lock(&substream->self_group.lock);
- res = snd_pcm_action_group(ops, substream, state, 1);
- spin_unlock(&substream->self_group.lock);
- spin_unlock(&substream->group->lock);
- } else {
- spin_lock(&substream->self_group.lock);
- res = snd_pcm_action_single(ops, substream, state);
- spin_unlock(&substream->self_group.lock);
- }
- read_unlock_irq(&snd_pcm_link_rwlock);
- return res;
-}
-
-/*
- */
-static int snd_pcm_action_nonatomic(struct action_ops *ops,
- struct snd_pcm_substream *substream,
- int state)
-{
- int res;
-
- down_read(&snd_pcm_link_rwsem);
- if (snd_pcm_stream_linked(substream))
- res = snd_pcm_action_group(ops, substream, state, 0);
- else
- res = snd_pcm_action_single(ops, substream, state);
- up_read(&snd_pcm_link_rwsem);
- return res;
-}
-
-/*
- * start callbacks
- */
-static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
- return -EBADFD;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
- !snd_pcm_playback_data(substream))
- return -EPIPE;
- runtime->trigger_master = substream;
- return 0;
-}
-
-static int snd_pcm_do_start(struct snd_pcm_substream *substream, int state)
-{
- if (substream->runtime->trigger_master != substream)
- return 0;
- return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
-}
-
-static void snd_pcm_undo_start(struct snd_pcm_substream *substream, int state)
-{
- if (substream->runtime->trigger_master == substream)
- substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
-}
-
-static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_trigger_tstamp(substream);
- runtime->hw_ptr_jiffies = jiffies;
- runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) /
- runtime->rate;
- runtime->status->state = state;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
- runtime->silence_size > 0)
- snd_pcm_playback_silence(substream, ULONG_MAX);
- if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTART,
- &runtime->trigger_tstamp);
-}
-
-static struct action_ops snd_pcm_action_start = {
- .pre_action = snd_pcm_pre_start,
- .do_action = snd_pcm_do_start,
- .undo_action = snd_pcm_undo_start,
- .post_action = snd_pcm_post_start
-};
-
-/**
- * snd_pcm_start - start all linked streams
- * @substream: the PCM substream instance
- */
-int snd_pcm_start(struct snd_pcm_substream *substream)
-{
- return snd_pcm_action(&snd_pcm_action_start, substream,
- SNDRV_PCM_STATE_RUNNING);
-}
-
-/*
- * stop callbacks
- */
-static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- runtime->trigger_master = substream;
- return 0;
-}
-
-static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
-{
- if (substream->runtime->trigger_master == substream &&
- snd_pcm_running(substream))
- substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
- return 0; /* unconditonally stop all substreams */
-}
-
-static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->status->state != state) {
- snd_pcm_trigger_tstamp(substream);
- if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP,
- &runtime->trigger_tstamp);
- runtime->status->state = state;
- }
- wake_up(&runtime->sleep);
- wake_up(&runtime->tsleep);
-}
-
-static struct action_ops snd_pcm_action_stop = {
- .pre_action = snd_pcm_pre_stop,
- .do_action = snd_pcm_do_stop,
- .post_action = snd_pcm_post_stop
-};
-
-/**
- * snd_pcm_stop - try to stop all running streams in the substream group
- * @substream: the PCM substream instance
- * @state: PCM state after stopping the stream
- *
- * The state of each stream is then changed to the given state unconditionally.
- */
-int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
-{
- return snd_pcm_action(&snd_pcm_action_stop, substream, state);
-}
-
-EXPORT_SYMBOL(snd_pcm_stop);
-
-/**
- * snd_pcm_drain_done - stop the DMA only when the given stream is playback
- * @substream: the PCM substream
- *
- * After stopping, the state is changed to SETUP.
- * Unlike snd_pcm_stop(), this affects only the given stream.
- */
-int snd_pcm_drain_done(struct snd_pcm_substream *substream)
-{
- return snd_pcm_action_single(&snd_pcm_action_stop, substream,
- SNDRV_PCM_STATE_SETUP);
-}
-
-/*
- * pause callbacks
- */
-static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (!(runtime->info & SNDRV_PCM_INFO_PAUSE))
- return -ENOSYS;
- if (push) {
- if (runtime->status->state != SNDRV_PCM_STATE_RUNNING)
- return -EBADFD;
- } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED)
- return -EBADFD;
- runtime->trigger_master = substream;
- return 0;
-}
-
-static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
-{
- if (substream->runtime->trigger_master != substream)
- return 0;
- /* some drivers might use hw_ptr to recover from the pause -
- update the hw_ptr now */
- if (push)
- snd_pcm_update_hw_ptr(substream);
- /* The jiffies check in snd_pcm_update_hw_ptr*() is done by
- * a delta between the current jiffies, this gives a large enough
- * delta, effectively to skip the check once.
- */
- substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
- return substream->ops->trigger(substream,
- push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
- SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
-}
-
-static void snd_pcm_undo_pause(struct snd_pcm_substream *substream, int push)
-{
- if (substream->runtime->trigger_master == substream)
- substream->ops->trigger(substream,
- push ? SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
- SNDRV_PCM_TRIGGER_PAUSE_PUSH);
-}
-
-static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_trigger_tstamp(substream);
- if (push) {
- runtime->status->state = SNDRV_PCM_STATE_PAUSED;
- if (substream->timer)
- snd_timer_notify(substream->timer,
- SNDRV_TIMER_EVENT_MPAUSE,
- &runtime->trigger_tstamp);
- wake_up(&runtime->sleep);
- wake_up(&runtime->tsleep);
- } else {
- runtime->status->state = SNDRV_PCM_STATE_RUNNING;
- if (substream->timer)
- snd_timer_notify(substream->timer,
- SNDRV_TIMER_EVENT_MCONTINUE,
- &runtime->trigger_tstamp);
- }
-}
-
-static struct action_ops snd_pcm_action_pause = {
- .pre_action = snd_pcm_pre_pause,
- .do_action = snd_pcm_do_pause,
- .undo_action = snd_pcm_undo_pause,
- .post_action = snd_pcm_post_pause
-};
-
-/*
- * Push/release the pause for all linked streams.
- */
-static int snd_pcm_pause(struct snd_pcm_substream *substream, int push)
-{
- return snd_pcm_action(&snd_pcm_action_pause, substream, push);
-}
-
-#ifdef CONFIG_PM
-/* suspend */
-
-static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
- return -EBUSY;
- runtime->trigger_master = substream;
- return 0;
-}
-
-static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->trigger_master != substream)
- return 0;
- if (! snd_pcm_running(substream))
- return 0;
- substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
- return 0; /* suspend unconditionally */
-}
-
-static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_trigger_tstamp(substream);
- if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSUSPEND,
- &runtime->trigger_tstamp);
- runtime->status->suspended_state = runtime->status->state;
- runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
- wake_up(&runtime->sleep);
- wake_up(&runtime->tsleep);
-}
-
-static struct action_ops snd_pcm_action_suspend = {
- .pre_action = snd_pcm_pre_suspend,
- .do_action = snd_pcm_do_suspend,
- .post_action = snd_pcm_post_suspend
-};
-
-/**
- * snd_pcm_suspend - trigger SUSPEND to all linked streams
- * @substream: the PCM substream
- *
- * After this call, all streams are changed to SUSPENDED state.
- */
-int snd_pcm_suspend(struct snd_pcm_substream *substream)
-{
- int err;
- unsigned long flags;
-
- if (! substream)
- return 0;
-
- snd_pcm_stream_lock_irqsave(substream, flags);
- err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
- snd_pcm_stream_unlock_irqrestore(substream, flags);
- return err;
-}
-
-EXPORT_SYMBOL(snd_pcm_suspend);
-
-/**
- * snd_pcm_suspend_all - trigger SUSPEND to all substreams in the given pcm
- * @pcm: the PCM instance
- *
- * After this call, all streams are changed to SUSPENDED state.
- */
-int snd_pcm_suspend_all(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- int stream, err = 0;
-
- if (! pcm)
- return 0;
-
- for (stream = 0; stream < 2; stream++) {
- for (substream = pcm->streams[stream].substream;
- substream; substream = substream->next) {
- /* FIXME: the open/close code should lock this as well */
- if (substream->runtime == NULL)
- continue;
- err = snd_pcm_suspend(substream);
- if (err < 0 && err != -EBUSY)
- return err;
- }
- }
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_suspend_all);
-
-/* resume */
-
-static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (!(runtime->info & SNDRV_PCM_INFO_RESUME))
- return -ENOSYS;
- runtime->trigger_master = substream;
- return 0;
-}
-
-static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->trigger_master != substream)
- return 0;
- /* DMA not running previously? */
- if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING &&
- (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING ||
- substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
- return 0;
- return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
-}
-
-static void snd_pcm_undo_resume(struct snd_pcm_substream *substream, int state)
-{
- if (substream->runtime->trigger_master == substream &&
- snd_pcm_running(substream))
- substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
-}
-
-static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_trigger_tstamp(substream);
- if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MRESUME,
- &runtime->trigger_tstamp);
- runtime->status->state = runtime->status->suspended_state;
-}
-
-static struct action_ops snd_pcm_action_resume = {
- .pre_action = snd_pcm_pre_resume,
- .do_action = snd_pcm_do_resume,
- .undo_action = snd_pcm_undo_resume,
- .post_action = snd_pcm_post_resume
-};
-
-static int snd_pcm_resume(struct snd_pcm_substream *substream)
-{
- struct snd_card *card = substream->pcm->card;
- int res;
-
- snd_power_lock(card);
- if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
- res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
- snd_power_unlock(card);
- return res;
-}
-
-#else
-
-static int snd_pcm_resume(struct snd_pcm_substream *substream)
-{
- return -ENOSYS;
-}
-
-#endif /* CONFIG_PM */
-
-/*
- * xrun ioctl
- *
- * Change the RUNNING stream(s) to XRUN state.
- */
-static int snd_pcm_xrun(struct snd_pcm_substream *substream)
-{
- struct snd_card *card = substream->pcm->card;
- struct snd_pcm_runtime *runtime = substream->runtime;
- int result;
-
- snd_power_lock(card);
- if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (result < 0)
- goto _unlock;
- }
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_XRUN:
- result = 0; /* already there */
- break;
- case SNDRV_PCM_STATE_RUNNING:
- result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
- break;
- default:
- result = -EBADFD;
- }
- snd_pcm_stream_unlock_irq(substream);
- _unlock:
- snd_power_unlock(card);
- return result;
-}
-
-/*
- * reset ioctl
- */
-static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_PAUSED:
- case SNDRV_PCM_STATE_SUSPENDED:
- return 0;
- default:
- return -EBADFD;
- }
-}
-
-static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
- if (err < 0)
- return err;
- runtime->hw_ptr_base = 0;
- runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
- runtime->status->hw_ptr % runtime->period_size;
- runtime->silence_start = runtime->status->hw_ptr;
- runtime->silence_filled = 0;
- return 0;
-}
-
-static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- runtime->control->appl_ptr = runtime->status->hw_ptr;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
- runtime->silence_size > 0)
- snd_pcm_playback_silence(substream, ULONG_MAX);
-}
-
-static struct action_ops snd_pcm_action_reset = {
- .pre_action = snd_pcm_pre_reset,
- .do_action = snd_pcm_do_reset,
- .post_action = snd_pcm_post_reset
-};
-
-static int snd_pcm_reset(struct snd_pcm_substream *substream)
-{
- return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
-}
-
-/*
- * prepare ioctl
- */
-/* we use the second argument for updating f_flags */
-static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
- int f_flags)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
- return -EBADFD;
- if (snd_pcm_running(substream))
- return -EBUSY;
- substream->f_flags = f_flags;
- return 0;
-}
-
-static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, int state)
-{
- int err;
- err = substream->ops->prepare(substream);
- if (err < 0)
- return err;
- return snd_pcm_do_reset(substream, 0);
-}
-
-static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- runtime->control->appl_ptr = runtime->status->hw_ptr;
- snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
-}
-
-static struct action_ops snd_pcm_action_prepare = {
- .pre_action = snd_pcm_pre_prepare,
- .do_action = snd_pcm_do_prepare,
- .post_action = snd_pcm_post_prepare
-};
-
-/**
- * snd_pcm_prepare - prepare the PCM substream to be triggerable
- * @substream: the PCM substream instance
- * @file: file to refer f_flags
- */
-static int snd_pcm_prepare(struct snd_pcm_substream *substream,
- struct file *file)
-{
- int res;
- struct snd_card *card = substream->pcm->card;
- int f_flags;
-
- if (file)
- f_flags = file->f_flags;
- else
- f_flags = substream->f_flags;
-
- snd_power_lock(card);
- if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
- res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
- substream, f_flags);
- snd_power_unlock(card);
- return res;
-}
-
-/*
- * drain ioctl
- */
-
-static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
-{
- substream->runtime->trigger_master = substream;
- return 0;
-}
-
-static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- /* start playback stream if possible */
- if (! snd_pcm_playback_empty(substream)) {
- snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING);
- snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING);
- }
- break;
- case SNDRV_PCM_STATE_RUNNING:
- runtime->status->state = SNDRV_PCM_STATE_DRAINING;
- break;
- default:
- break;
- }
- } else {
- /* stop running stream */
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
- int new_state = snd_pcm_capture_avail(runtime) > 0 ?
- SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
- snd_pcm_do_stop(substream, new_state);
- snd_pcm_post_stop(substream, new_state);
- }
- }
- return 0;
-}
-
-static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int state)
-{
-}
-
-static struct action_ops snd_pcm_action_drain_init = {
- .pre_action = snd_pcm_pre_drain_init,
- .do_action = snd_pcm_do_drain_init,
- .post_action = snd_pcm_post_drain_init
-};
-
-static int snd_pcm_drop(struct snd_pcm_substream *substream);
-
-/*
- * Drain the stream(s).
- * When the substream is linked, sync until the draining of all playback streams
- * is finished.
- * After this call, all streams are supposed to be either SETUP or DRAINING
- * (capture only) state.
- */
-static int snd_pcm_drain(struct snd_pcm_substream *substream,
- struct file *file)
-{
- struct snd_card *card;
- struct snd_pcm_runtime *runtime;
- struct snd_pcm_substream *s;
- wait_queue_t wait;
- int result = 0;
- int nonblock = 0;
-
- card = substream->pcm->card;
- runtime = substream->runtime;
-
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
-
- snd_power_lock(card);
- if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (result < 0) {
- snd_power_unlock(card);
- return result;
- }
- }
-
- if (file) {
- if (file->f_flags & O_NONBLOCK)
- nonblock = 1;
- } else if (substream->f_flags & O_NONBLOCK)
- nonblock = 1;
-
- down_read(&snd_pcm_link_rwsem);
- snd_pcm_stream_lock_irq(substream);
- /* resume pause */
- if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
- snd_pcm_pause(substream, 0);
-
- /* pre-start/stop - all running streams are changed to DRAINING state */
- result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
- if (result < 0)
- goto unlock;
- /* in non-blocking, we don't wait in ioctl but let caller poll */
- if (nonblock) {
- result = -EAGAIN;
- goto unlock;
- }
-
- for (;;) {
- long tout;
- struct snd_pcm_runtime *to_check;
- if (signal_pending(current)) {
- result = -ERESTARTSYS;
- break;
- }
- /* find a substream to drain */
- to_check = NULL;
- snd_pcm_group_for_each_entry(s, substream) {
- if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
- continue;
- runtime = s->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
- to_check = runtime;
- break;
- }
- }
- if (!to_check)
- break; /* all drained */
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&to_check->sleep, &wait);
- snd_pcm_stream_unlock_irq(substream);
- up_read(&snd_pcm_link_rwsem);
- snd_power_unlock(card);
- if (runtime->no_period_wakeup)
- tout = MAX_SCHEDULE_TIMEOUT;
- else {
- tout = 10;
- if (runtime->rate) {
- long t = runtime->period_size * 2 / runtime->rate;
- tout = max(t, tout);
- }
- tout = msecs_to_jiffies(tout * 1000);
- }
- tout = schedule_timeout_interruptible(tout);
- snd_power_lock(card);
- down_read(&snd_pcm_link_rwsem);
- snd_pcm_stream_lock_irq(substream);
- remove_wait_queue(&to_check->sleep, &wait);
- if (card->shutdown) {
- result = -ENODEV;
- break;
- }
- if (tout == 0) {
- if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
- result = -ESTRPIPE;
- else {
- snd_printd("playback drain error (DMA or IRQ trouble?)\n");
- snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
- result = -EIO;
- }
- break;
- }
- }
-
- unlock:
- snd_pcm_stream_unlock_irq(substream);
- up_read(&snd_pcm_link_rwsem);
- snd_power_unlock(card);
-
- return result;
-}
-
-/*
- * drop ioctl
- *
- * Immediately put all linked substreams into SETUP state.
- */
-static int snd_pcm_drop(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
- int result = 0;
-
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
-
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED ||
- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
- return -EBADFD;
-
- snd_pcm_stream_lock_irq(substream);
- /* resume pause */
- if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
- snd_pcm_pause(substream, 0);
-
- snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
- /* runtime->control->appl_ptr = runtime->status->hw_ptr; */
- snd_pcm_stream_unlock_irq(substream);
-
- return result;
-}
-
-
-/* WARNING: Don't forget to fput back the file */
-static struct file *snd_pcm_file_fd(int fd)
-{
- struct file *file;
- struct inode *inode;
- unsigned int minor;
-
- file = fget(fd);
- if (!file)
- return NULL;
- inode = file->f_path.dentry->d_inode;
- if (!S_ISCHR(inode->i_mode) ||
- imajor(inode) != snd_major) {
- fput(file);
- return NULL;
- }
- minor = iminor(inode);
- if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) &&
- !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) {
- fput(file);
- return NULL;
- }
- return file;
-}
-
-/*
- * PCM link handling
- */
-static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
-{
- int res = 0;
- struct file *file;
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream1;
- struct snd_pcm_group *group;
-
- file = snd_pcm_file_fd(fd);
- if (!file)
- return -EBADFD;
- pcm_file = file->private_data;
- substream1 = pcm_file->substream;
- group = kmalloc(sizeof(*group), GFP_KERNEL);
- if (!group) {
- res = -ENOMEM;
- goto _nolock;
- }
- down_write(&snd_pcm_link_rwsem);
- write_lock_irq(&snd_pcm_link_rwlock);
- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
- substream->runtime->status->state != substream1->runtime->status->state) {
- res = -EBADFD;
- goto _end;
- }
- if (snd_pcm_stream_linked(substream1)) {
- res = -EALREADY;
- goto _end;
- }
- if (!snd_pcm_stream_linked(substream)) {
- substream->group = group;
- spin_lock_init(&substream->group->lock);
- INIT_LIST_HEAD(&substream->group->substreams);
- list_add_tail(&substream->link_list, &substream->group->substreams);
- substream->group->count = 1;
- }
- list_add_tail(&substream1->link_list, &substream->group->substreams);
- substream->group->count++;
- substream1->group = substream->group;
- _end:
- write_unlock_irq(&snd_pcm_link_rwlock);
- up_write(&snd_pcm_link_rwsem);
- _nolock:
- snd_card_unref(substream1->pcm->card);
- fput(file);
- if (res < 0)
- kfree(group);
- return res;
-}
-
-static void relink_to_local(struct snd_pcm_substream *substream)
-{
- substream->group = &substream->self_group;
- INIT_LIST_HEAD(&substream->self_group.substreams);
- list_add_tail(&substream->link_list, &substream->self_group.substreams);
-}
-
-static int snd_pcm_unlink(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_substream *s;
- int res = 0;
-
- down_write(&snd_pcm_link_rwsem);
- write_lock_irq(&snd_pcm_link_rwlock);
- if (!snd_pcm_stream_linked(substream)) {
- res = -EALREADY;
- goto _end;
- }
- list_del(&substream->link_list);
- substream->group->count--;
- if (substream->group->count == 1) { /* detach the last stream, too */
- snd_pcm_group_for_each_entry(s, substream) {
- relink_to_local(s);
- break;
- }
- kfree(substream->group);
- }
- relink_to_local(substream);
- _end:
- write_unlock_irq(&snd_pcm_link_rwlock);
- up_write(&snd_pcm_link_rwsem);
- return res;
-}
-
-/*
- * hw configurator
- */
-static int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval t;
- snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
- hw_param_interval_c(params, rule->deps[1]), &t);
- return snd_interval_refine(hw_param_interval(params, rule->var), &t);
-}
-
-static int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval t;
- snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
- hw_param_interval_c(params, rule->deps[1]), &t);
- return snd_interval_refine(hw_param_interval(params, rule->var), &t);
-}
-
-static int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval t;
- snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]),
- hw_param_interval_c(params, rule->deps[1]),
- (unsigned long) rule->private, &t);
- return snd_interval_refine(hw_param_interval(params, rule->var), &t);
-}
-
-static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval t;
- snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
- (unsigned long) rule->private,
- hw_param_interval_c(params, rule->deps[1]), &t);
- return snd_interval_refine(hw_param_interval(params, rule->var), &t);
-}
-
-static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- unsigned int k;
- struct snd_interval *i = hw_param_interval(params, rule->deps[0]);
- struct snd_mask m;
- struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
- snd_mask_any(&m);
- for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
- int bits;
- if (! snd_mask_test(mask, k))
- continue;
- bits = snd_pcm_format_physical_width(k);
- if (bits <= 0)
- continue; /* ignore invalid formats */
- if ((unsigned)bits < i->min || (unsigned)bits > i->max)
- snd_mask_reset(&m, k);
- }
- return snd_mask_refine(mask, &m);
-}
-
-static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval t;
- unsigned int k;
- t.min = UINT_MAX;
- t.max = 0;
- t.openmin = 0;
- t.openmax = 0;
- for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
- int bits;
- if (! snd_mask_test(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k))
- continue;
- bits = snd_pcm_format_physical_width(k);
- if (bits <= 0)
- continue; /* ignore invalid formats */
- if (t.min > (unsigned)bits)
- t.min = bits;
- if (t.max < (unsigned)bits)
- t.max = bits;
- }
- t.integer = 1;
- return snd_interval_refine(hw_param_interval(params, rule->var), &t);
-}
-
-#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
-#error "Change this table"
-#endif
-
-static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
- 48000, 64000, 88200, 96000, 176400, 192000 };
-
-const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
- .count = ARRAY_SIZE(rates),
- .list = rates,
-};
-
-static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_pcm_hardware *hw = rule->private;
- return snd_interval_list(hw_param_interval(params, rule->var),
- snd_pcm_known_rates.count,
- snd_pcm_known_rates.list, hw->rates);
-}
-
-static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval t;
- struct snd_pcm_substream *substream = rule->private;
- t.min = 0;
- t.max = substream->buffer_bytes_max;
- t.openmin = 0;
- t.openmax = 0;
- t.integer = 1;
- return snd_interval_refine(hw_param_interval(params, rule->var), &t);
-}
-
-int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
- int k, err;
-
- for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
- snd_mask_any(constrs_mask(constrs, k));
- }
-
- for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
- snd_interval_any(constrs_interval(constrs, k));
- }
-
- snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_CHANNELS));
- snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_SIZE));
- snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_BYTES));
- snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_SAMPLE_BITS));
- snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_FRAME_BITS));
-
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
- snd_pcm_hw_rule_format, NULL,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
- snd_pcm_hw_rule_sample_bits, NULL,
- SNDRV_PCM_HW_PARAM_FORMAT,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
- snd_pcm_hw_rule_div, NULL,
- SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS,
- snd_pcm_hw_rule_mul, NULL,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS,
- snd_pcm_hw_rule_mulkdiv, (void*) 8,
- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS,
- snd_pcm_hw_rule_mulkdiv, (void*) 8,
- SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- snd_pcm_hw_rule_div, NULL,
- SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_TIME, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_BUFFER_TIME, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS,
- snd_pcm_hw_rule_div, NULL,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- snd_pcm_hw_rule_div, NULL,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- snd_pcm_hw_rule_mulkdiv, (void*) 8,
- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- snd_pcm_hw_rule_muldivk, (void*) 1000000,
- SNDRV_PCM_HW_PARAM_PERIOD_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
- snd_pcm_hw_rule_mul, NULL,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
- snd_pcm_hw_rule_mulkdiv, (void*) 8,
- SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
- snd_pcm_hw_rule_muldivk, (void*) 1000000,
- SNDRV_PCM_HW_PARAM_BUFFER_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
- snd_pcm_hw_rule_muldivk, (void*) 8,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
- snd_pcm_hw_rule_muldivk, (void*) 8,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
- snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
- snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);
- if (err < 0)
- return err;
- return 0;
-}
-
-int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_pcm_hardware *hw = &runtime->hw;
- int err;
- unsigned int mask = 0;
-
- if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
- mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED;
- if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
- mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;
- if (hw->info & SNDRV_PCM_INFO_MMAP) {
- if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
- mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
- if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
- mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED;
- if (hw->info & SNDRV_PCM_INFO_COMPLEX)
- mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX;
- }
- err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask);
- if (err < 0)
- return err;
-
- err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
- if (err < 0)
- return err;
-
- err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);
- if (err < 0)
- return err;
-
- err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS,
- hw->channels_min, hw->channels_max);
- if (err < 0)
- return err;
-
- err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
- hw->rate_min, hw->rate_max);
- if (err < 0)
- return err;
-
- err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
- hw->period_bytes_min, hw->period_bytes_max);
- if (err < 0)
- return err;
-
- err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
- hw->periods_min, hw->periods_max);
- if (err < 0)
- return err;
-
- err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
- hw->period_bytes_min, hw->buffer_bytes_max);
- if (err < 0)
- return err;
-
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
- snd_pcm_hw_rule_buffer_bytes_max, substream,
- SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
- if (err < 0)
- return err;
-
- /* FIXME: remove */
- if (runtime->dma_bytes) {
- err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes);
- if (err < 0)
- return -EINVAL;
- }
-
- if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) {
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- snd_pcm_hw_rule_rate, hw,
- SNDRV_PCM_HW_PARAM_RATE, -1);
- if (err < 0)
- return err;
- }
-
- /* FIXME: this belong to lowlevel */
- snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
-
- return 0;
-}
-
-static void pcm_release_private(struct snd_pcm_substream *substream)
-{
- snd_pcm_unlink(substream);
-}
-
-void snd_pcm_release_substream(struct snd_pcm_substream *substream)
-{
- substream->ref_count--;
- if (substream->ref_count > 0)
- return;
-
- snd_pcm_drop(substream);
- if (substream->hw_opened) {
- if (substream->ops->hw_free != NULL)
- substream->ops->hw_free(substream);
- substream->ops->close(substream);
- substream->hw_opened = 0;
- }
- if (pm_qos_request_active(&substream->latency_pm_qos_req))
- pm_qos_remove_request(&substream->latency_pm_qos_req);
- if (substream->pcm_release) {
- substream->pcm_release(substream);
- substream->pcm_release = NULL;
- }
- snd_pcm_detach_substream(substream);
-}
-
-EXPORT_SYMBOL(snd_pcm_release_substream);
-
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
- struct file *file,
- struct snd_pcm_substream **rsubstream)
-{
- struct snd_pcm_substream *substream;
- int err;
-
- err = snd_pcm_attach_substream(pcm, stream, file, &substream);
- if (err < 0)
- return err;
- if (substream->ref_count > 1) {
- *rsubstream = substream;
- return 0;
- }
-
- err = snd_pcm_hw_constraints_init(substream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraints_init failed\n");
- goto error;
- }
-
- if ((err = substream->ops->open(substream)) < 0)
- goto error;
-
- substream->hw_opened = 1;
-
- err = snd_pcm_hw_constraints_complete(substream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraints_complete failed\n");
- goto error;
- }
-
- *rsubstream = substream;
- return 0;
-
- error:
- snd_pcm_release_substream(substream);
- return err;
-}
-
-EXPORT_SYMBOL(snd_pcm_open_substream);
-
-static int snd_pcm_open_file(struct file *file,
- struct snd_pcm *pcm,
- int stream)
-{
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream;
- int err;
-
- err = snd_pcm_open_substream(pcm, stream, file, &substream);
- if (err < 0)
- return err;
-
- pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
- if (pcm_file == NULL) {
- snd_pcm_release_substream(substream);
- return -ENOMEM;
- }
- pcm_file->substream = substream;
- if (substream->ref_count == 1) {
- substream->file = pcm_file;
- substream->pcm_release = pcm_release_private;
- }
- file->private_data = pcm_file;
-
- return 0;
-}
-
-static int snd_pcm_playback_open(struct inode *inode, struct file *file)
-{
- struct snd_pcm *pcm;
- int err = nonseekable_open(inode, file);
- if (err < 0)
- return err;
- pcm = snd_lookup_minor_data(iminor(inode),
- SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
- err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
- if (pcm)
- snd_card_unref(pcm->card);
- return err;
-}
-
-static int snd_pcm_capture_open(struct inode *inode, struct file *file)
-{
- struct snd_pcm *pcm;
- int err = nonseekable_open(inode, file);
- if (err < 0)
- return err;
- pcm = snd_lookup_minor_data(iminor(inode),
- SNDRV_DEVICE_TYPE_PCM_CAPTURE);
- err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
- if (pcm)
- snd_card_unref(pcm->card);
- return err;
-}
-
-static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
-{
- int err;
- wait_queue_t wait;
-
- if (pcm == NULL) {
- err = -ENODEV;
- goto __error1;
- }
- err = snd_card_file_add(pcm->card, file);
- if (err < 0)
- goto __error1;
- if (!try_module_get(pcm->card->module)) {
- err = -EFAULT;
- goto __error2;
- }
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&pcm->open_wait, &wait);
- mutex_lock(&pcm->open_mutex);
- while (1) {
- err = snd_pcm_open_file(file, pcm, stream);
- if (err >= 0)
- break;
- if (err == -EAGAIN) {
- if (file->f_flags & O_NONBLOCK) {
- err = -EBUSY;
- break;
- }
- } else
- break;
- set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&pcm->open_mutex);
- schedule();
- mutex_lock(&pcm->open_mutex);
- if (pcm->card->shutdown) {
- err = -ENODEV;
- break;
- }
- if (signal_pending(current)) {
- err = -ERESTARTSYS;
- break;
- }
- }
- remove_wait_queue(&pcm->open_wait, &wait);
- mutex_unlock(&pcm->open_mutex);
- if (err < 0)
- goto __error;
- return err;
-
- __error:
- module_put(pcm->card->module);
- __error2:
- snd_card_file_remove(pcm->card, file);
- __error1:
- return err;
-}
-
-static int snd_pcm_release(struct inode *inode, struct file *file)
-{
- struct snd_pcm *pcm;
- struct snd_pcm_substream *substream;
- struct snd_pcm_file *pcm_file;
-
- pcm_file = file->private_data;
- substream = pcm_file->substream;
- if (snd_BUG_ON(!substream))
- return -ENXIO;
- pcm = substream->pcm;
- mutex_lock(&pcm->open_mutex);
- snd_pcm_release_substream(substream);
- kfree(pcm_file);
- mutex_unlock(&pcm->open_mutex);
- wake_up(&pcm->open_wait);
- module_put(pcm->card->module);
- snd_card_file_remove(pcm->card, file);
- return 0;
-}
-
-static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t appl_ptr;
- snd_pcm_sframes_t ret;
- snd_pcm_sframes_t hw_avail;
-
- if (frames == 0)
- return 0;
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- break;
- case SNDRV_PCM_STATE_DRAINING:
- case SNDRV_PCM_STATE_RUNNING:
- if (snd_pcm_update_hw_ptr(substream) >= 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_XRUN:
- ret = -EPIPE;
- goto __end;
- case SNDRV_PCM_STATE_SUSPENDED:
- ret = -ESTRPIPE;
- goto __end;
- default:
- ret = -EBADFD;
- goto __end;
- }
-
- hw_avail = snd_pcm_playback_hw_avail(runtime);
- if (hw_avail <= 0) {
- ret = 0;
- goto __end;
- }
- if (frames > (snd_pcm_uframes_t)hw_avail)
- frames = hw_avail;
- appl_ptr = runtime->control->appl_ptr - frames;
- if (appl_ptr < 0)
- appl_ptr += runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- ret = frames;
- __end:
- snd_pcm_stream_unlock_irq(substream);
- return ret;
-}
-
-static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t appl_ptr;
- snd_pcm_sframes_t ret;
- snd_pcm_sframes_t hw_avail;
-
- if (frames == 0)
- return 0;
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_DRAINING:
- break;
- case SNDRV_PCM_STATE_RUNNING:
- if (snd_pcm_update_hw_ptr(substream) >= 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_XRUN:
- ret = -EPIPE;
- goto __end;
- case SNDRV_PCM_STATE_SUSPENDED:
- ret = -ESTRPIPE;
- goto __end;
- default:
- ret = -EBADFD;
- goto __end;
- }
-
- hw_avail = snd_pcm_capture_hw_avail(runtime);
- if (hw_avail <= 0) {
- ret = 0;
- goto __end;
- }
- if (frames > (snd_pcm_uframes_t)hw_avail)
- frames = hw_avail;
- appl_ptr = runtime->control->appl_ptr - frames;
- if (appl_ptr < 0)
- appl_ptr += runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- ret = frames;
- __end:
- snd_pcm_stream_unlock_irq(substream);
- return ret;
-}
-
-static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t appl_ptr;
- snd_pcm_sframes_t ret;
- snd_pcm_sframes_t avail;
-
- if (frames == 0)
- return 0;
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_PAUSED:
- break;
- case SNDRV_PCM_STATE_DRAINING:
- case SNDRV_PCM_STATE_RUNNING:
- if (snd_pcm_update_hw_ptr(substream) >= 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_XRUN:
- ret = -EPIPE;
- goto __end;
- case SNDRV_PCM_STATE_SUSPENDED:
- ret = -ESTRPIPE;
- goto __end;
- default:
- ret = -EBADFD;
- goto __end;
- }
-
- avail = snd_pcm_playback_avail(runtime);
- if (avail <= 0) {
- ret = 0;
- goto __end;
- }
- if (frames > (snd_pcm_uframes_t)avail)
- frames = avail;
- appl_ptr = runtime->control->appl_ptr + frames;
- if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
- appl_ptr -= runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- ret = frames;
- __end:
- snd_pcm_stream_unlock_irq(substream);
- return ret;
-}
-
-static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t appl_ptr;
- snd_pcm_sframes_t ret;
- snd_pcm_sframes_t avail;
-
- if (frames == 0)
- return 0;
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_DRAINING:
- case SNDRV_PCM_STATE_PAUSED:
- break;
- case SNDRV_PCM_STATE_RUNNING:
- if (snd_pcm_update_hw_ptr(substream) >= 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_XRUN:
- ret = -EPIPE;
- goto __end;
- case SNDRV_PCM_STATE_SUSPENDED:
- ret = -ESTRPIPE;
- goto __end;
- default:
- ret = -EBADFD;
- goto __end;
- }
-
- avail = snd_pcm_capture_avail(runtime);
- if (avail <= 0) {
- ret = 0;
- goto __end;
- }
- if (frames > (snd_pcm_uframes_t)avail)
- frames = avail;
- appl_ptr = runtime->control->appl_ptr + frames;
- if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
- appl_ptr -= runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- ret = frames;
- __end:
- snd_pcm_stream_unlock_irq(substream);
- return ret;
-}
-
-static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_DRAINING:
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- goto __badfd;
- case SNDRV_PCM_STATE_RUNNING:
- if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_SUSPENDED:
- err = 0;
- break;
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- break;
- default:
- __badfd:
- err = -EBADFD;
- break;
- }
- snd_pcm_stream_unlock_irq(substream);
- return err;
-}
-
-static int snd_pcm_delay(struct snd_pcm_substream *substream,
- snd_pcm_sframes_t __user *res)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- snd_pcm_sframes_t n = 0;
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_DRAINING:
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- goto __badfd;
- case SNDRV_PCM_STATE_RUNNING:
- if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_SUSPENDED:
- err = 0;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- n = snd_pcm_playback_hw_avail(runtime);
- else
- n = snd_pcm_capture_avail(runtime);
- n += runtime->delay;
- break;
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- break;
- default:
- __badfd:
- err = -EBADFD;
- break;
- }
- snd_pcm_stream_unlock_irq(substream);
- if (!err)
- if (put_user(n, res))
- err = -EFAULT;
- return err;
-}
-
-static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
- struct snd_pcm_sync_ptr __user *_sync_ptr)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_pcm_sync_ptr sync_ptr;
- volatile struct snd_pcm_mmap_status *status;
- volatile struct snd_pcm_mmap_control *control;
- int err;
-
- memset(&sync_ptr, 0, sizeof(sync_ptr));
- if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags)))
- return -EFAULT;
- if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct snd_pcm_mmap_control)))
- return -EFAULT;
- status = runtime->status;
- control = runtime->control;
- if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
- err = snd_pcm_hwsync(substream);
- if (err < 0)
- return err;
- }
- snd_pcm_stream_lock_irq(substream);
- if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
- control->appl_ptr = sync_ptr.c.control.appl_ptr;
- else
- sync_ptr.c.control.appl_ptr = control->appl_ptr;
- if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
- control->avail_min = sync_ptr.c.control.avail_min;
- else
- sync_ptr.c.control.avail_min = control->avail_min;
- sync_ptr.s.status.state = status->state;
- sync_ptr.s.status.hw_ptr = status->hw_ptr;
- sync_ptr.s.status.tstamp = status->tstamp;
- sync_ptr.s.status.suspended_state = status->suspended_state;
- snd_pcm_stream_unlock_irq(substream);
- if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int arg;
-
- if (get_user(arg, _arg))
- return -EFAULT;
- if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
- return -EINVAL;
- runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
- if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
- runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
- return 0;
-}
-
-static int snd_pcm_common_ioctl1(struct file *file,
- struct snd_pcm_substream *substream,
- unsigned int cmd, void __user *arg)
-{
- switch (cmd) {
- case SNDRV_PCM_IOCTL_PVERSION:
- return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
- case SNDRV_PCM_IOCTL_INFO:
- return snd_pcm_info_user(substream, arg);
- case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */
- return 0;
- case SNDRV_PCM_IOCTL_TTSTAMP:
- return snd_pcm_tstamp(substream, arg);
- case SNDRV_PCM_IOCTL_HW_REFINE:
- return snd_pcm_hw_refine_user(substream, arg);
- case SNDRV_PCM_IOCTL_HW_PARAMS:
- return snd_pcm_hw_params_user(substream, arg);
- case SNDRV_PCM_IOCTL_HW_FREE:
- return snd_pcm_hw_free(substream);
- case SNDRV_PCM_IOCTL_SW_PARAMS:
- return snd_pcm_sw_params_user(substream, arg);
- case SNDRV_PCM_IOCTL_STATUS:
- return snd_pcm_status_user(substream, arg);
- case SNDRV_PCM_IOCTL_CHANNEL_INFO:
- return snd_pcm_channel_info_user(substream, arg);
- case SNDRV_PCM_IOCTL_PREPARE:
- return snd_pcm_prepare(substream, file);
- case SNDRV_PCM_IOCTL_RESET:
- return snd_pcm_reset(substream);
- case SNDRV_PCM_IOCTL_START:
- return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING);
- case SNDRV_PCM_IOCTL_LINK:
- return snd_pcm_link(substream, (int)(unsigned long) arg);
- case SNDRV_PCM_IOCTL_UNLINK:
- return snd_pcm_unlink(substream);
- case SNDRV_PCM_IOCTL_RESUME:
- return snd_pcm_resume(substream);
- case SNDRV_PCM_IOCTL_XRUN:
- return snd_pcm_xrun(substream);
- case SNDRV_PCM_IOCTL_HWSYNC:
- return snd_pcm_hwsync(substream);
- case SNDRV_PCM_IOCTL_DELAY:
- return snd_pcm_delay(substream, arg);
- case SNDRV_PCM_IOCTL_SYNC_PTR:
- return snd_pcm_sync_ptr(substream, arg);
-#ifdef CONFIG_SND_SUPPORT_OLD_API
- case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
- return snd_pcm_hw_refine_old_user(substream, arg);
- case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
- return snd_pcm_hw_params_old_user(substream, arg);
-#endif
- case SNDRV_PCM_IOCTL_DRAIN:
- return snd_pcm_drain(substream, file);
- case SNDRV_PCM_IOCTL_DROP:
- return snd_pcm_drop(substream);
- case SNDRV_PCM_IOCTL_PAUSE:
- {
- int res;
- snd_pcm_stream_lock_irq(substream);
- res = snd_pcm_pause(substream, (int)(unsigned long)arg);
- snd_pcm_stream_unlock_irq(substream);
- return res;
- }
- }
- snd_printd("unknown ioctl = 0x%x\n", cmd);
- return -ENOTTY;
-}
-
-static int snd_pcm_playback_ioctl1(struct file *file,
- struct snd_pcm_substream *substream,
- unsigned int cmd, void __user *arg)
-{
- if (snd_BUG_ON(!substream))
- return -ENXIO;
- if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
- return -EINVAL;
- switch (cmd) {
- case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
- {
- struct snd_xferi xferi;
- struct snd_xferi __user *_xferi = arg;
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t result;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (put_user(0, &_xferi->result))
- return -EFAULT;
- if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
- return -EFAULT;
- result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
- __put_user(result, &_xferi->result);
- return result < 0 ? result : 0;
- }
- case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
- {
- struct snd_xfern xfern;
- struct snd_xfern __user *_xfern = arg;
- struct snd_pcm_runtime *runtime = substream->runtime;
- void __user **bufs;
- snd_pcm_sframes_t result;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (runtime->channels > 128)
- return -EINVAL;
- if (put_user(0, &_xfern->result))
- return -EFAULT;
- if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
- return -EFAULT;
-
- bufs = memdup_user(xfern.bufs,
- sizeof(void *) * runtime->channels);
- if (IS_ERR(bufs))
- return PTR_ERR(bufs);
- result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
- kfree(bufs);
- __put_user(result, &_xfern->result);
- return result < 0 ? result : 0;
- }
- case SNDRV_PCM_IOCTL_REWIND:
- {
- snd_pcm_uframes_t frames;
- snd_pcm_uframes_t __user *_frames = arg;
- snd_pcm_sframes_t result;
- if (get_user(frames, _frames))
- return -EFAULT;
- if (put_user(0, _frames))
- return -EFAULT;
- result = snd_pcm_playback_rewind(substream, frames);
- __put_user(result, _frames);
- return result < 0 ? result : 0;
- }
- case SNDRV_PCM_IOCTL_FORWARD:
- {
- snd_pcm_uframes_t frames;
- snd_pcm_uframes_t __user *_frames = arg;
- snd_pcm_sframes_t result;
- if (get_user(frames, _frames))
- return -EFAULT;
- if (put_user(0, _frames))
- return -EFAULT;
- result = snd_pcm_playback_forward(substream, frames);
- __put_user(result, _frames);
- return result < 0 ? result : 0;
- }
- }
- return snd_pcm_common_ioctl1(file, substream, cmd, arg);
-}
-
-static int snd_pcm_capture_ioctl1(struct file *file,
- struct snd_pcm_substream *substream,
- unsigned int cmd, void __user *arg)
-{
- if (snd_BUG_ON(!substream))
- return -ENXIO;
- if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE))
- return -EINVAL;
- switch (cmd) {
- case SNDRV_PCM_IOCTL_READI_FRAMES:
- {
- struct snd_xferi xferi;
- struct snd_xferi __user *_xferi = arg;
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t result;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (put_user(0, &_xferi->result))
- return -EFAULT;
- if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
- return -EFAULT;
- result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
- __put_user(result, &_xferi->result);
- return result < 0 ? result : 0;
- }
- case SNDRV_PCM_IOCTL_READN_FRAMES:
- {
- struct snd_xfern xfern;
- struct snd_xfern __user *_xfern = arg;
- struct snd_pcm_runtime *runtime = substream->runtime;
- void *bufs;
- snd_pcm_sframes_t result;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (runtime->channels > 128)
- return -EINVAL;
- if (put_user(0, &_xfern->result))
- return -EFAULT;
- if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
- return -EFAULT;
-
- bufs = memdup_user(xfern.bufs,
- sizeof(void *) * runtime->channels);
- if (IS_ERR(bufs))
- return PTR_ERR(bufs);
- result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
- kfree(bufs);
- __put_user(result, &_xfern->result);
- return result < 0 ? result : 0;
- }
- case SNDRV_PCM_IOCTL_REWIND:
- {
- snd_pcm_uframes_t frames;
- snd_pcm_uframes_t __user *_frames = arg;
- snd_pcm_sframes_t result;
- if (get_user(frames, _frames))
- return -EFAULT;
- if (put_user(0, _frames))
- return -EFAULT;
- result = snd_pcm_capture_rewind(substream, frames);
- __put_user(result, _frames);
- return result < 0 ? result : 0;
- }
- case SNDRV_PCM_IOCTL_FORWARD:
- {
- snd_pcm_uframes_t frames;
- snd_pcm_uframes_t __user *_frames = arg;
- snd_pcm_sframes_t result;
- if (get_user(frames, _frames))
- return -EFAULT;
- if (put_user(0, _frames))
- return -EFAULT;
- result = snd_pcm_capture_forward(substream, frames);
- __put_user(result, _frames);
- return result < 0 ? result : 0;
- }
- }
- return snd_pcm_common_ioctl1(file, substream, cmd, arg);
-}
-
-static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct snd_pcm_file *pcm_file;
-
- pcm_file = file->private_data;
-
- if (((cmd >> 8) & 0xff) != 'A')
- return -ENOTTY;
-
- return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
- (void __user *)arg);
-}
-
-static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct snd_pcm_file *pcm_file;
-
- pcm_file = file->private_data;
-
- if (((cmd >> 8) & 0xff) != 'A')
- return -ENOTTY;
-
- return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
- (void __user *)arg);
-}
-
-int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
- mm_segment_t fs;
- int result;
-
- fs = snd_enter_user();
- switch (substream->stream) {
- case SNDRV_PCM_STREAM_PLAYBACK:
- result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
- (void __user *)arg);
- break;
- case SNDRV_PCM_STREAM_CAPTURE:
- result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
- (void __user *)arg);
- break;
- default:
- result = -EINVAL;
- break;
- }
- snd_leave_user(fs);
- return result;
-}
-
-EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
-
-static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
- loff_t * offset)
-{
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- snd_pcm_sframes_t result;
-
- pcm_file = file->private_data;
- substream = pcm_file->substream;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (!frame_aligned(runtime, count))
- return -EINVAL;
- count = bytes_to_frames(runtime, count);
- result = snd_pcm_lib_read(substream, buf, count);
- if (result > 0)
- result = frames_to_bytes(runtime, result);
- return result;
-}
-
-static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
- size_t count, loff_t * offset)
-{
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- snd_pcm_sframes_t result;
-
- pcm_file = file->private_data;
- substream = pcm_file->substream;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (!frame_aligned(runtime, count))
- return -EINVAL;
- count = bytes_to_frames(runtime, count);
- result = snd_pcm_lib_write(substream, buf, count);
- if (result > 0)
- result = frames_to_bytes(runtime, result);
- return result;
-}
-
-static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
-
-{
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- snd_pcm_sframes_t result;
- unsigned long i;
- void __user **bufs;
- snd_pcm_uframes_t frames;
-
- pcm_file = iocb->ki_filp->private_data;
- substream = pcm_file->substream;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (nr_segs > 1024 || nr_segs != runtime->channels)
- return -EINVAL;
- if (!frame_aligned(runtime, iov->iov_len))
- return -EINVAL;
- frames = bytes_to_samples(runtime, iov->iov_len);
- bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL);
- if (bufs == NULL)
- return -ENOMEM;
- for (i = 0; i < nr_segs; ++i)
- bufs[i] = iov[i].iov_base;
- result = snd_pcm_lib_readv(substream, bufs, frames);
- if (result > 0)
- result = frames_to_bytes(runtime, result);
- kfree(bufs);
- return result;
-}
-
-static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
-{
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- snd_pcm_sframes_t result;
- unsigned long i;
- void __user **bufs;
- snd_pcm_uframes_t frames;
-
- pcm_file = iocb->ki_filp->private_data;
- substream = pcm_file->substream;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (nr_segs > 128 || nr_segs != runtime->channels ||
- !frame_aligned(runtime, iov->iov_len))
- return -EINVAL;
- frames = bytes_to_samples(runtime, iov->iov_len);
- bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL);
- if (bufs == NULL)
- return -ENOMEM;
- for (i = 0; i < nr_segs; ++i)
- bufs[i] = iov[i].iov_base;
- result = snd_pcm_lib_writev(substream, bufs, frames);
- if (result > 0)
- result = frames_to_bytes(runtime, result);
- kfree(bufs);
- return result;
-}
-
-static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
-{
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- unsigned int mask;
- snd_pcm_uframes_t avail;
-
- pcm_file = file->private_data;
-
- substream = pcm_file->substream;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
-
- poll_wait(file, &runtime->sleep, wait);
-
- snd_pcm_stream_lock_irq(substream);
- avail = snd_pcm_playback_avail(runtime);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_PAUSED:
- if (avail >= runtime->control->avail_min) {
- mask = POLLOUT | POLLWRNORM;
- break;
- }
- /* Fall through */
- case SNDRV_PCM_STATE_DRAINING:
- mask = 0;
- break;
- default:
- mask = POLLOUT | POLLWRNORM | POLLERR;
- break;
- }
- snd_pcm_stream_unlock_irq(substream);
- return mask;
-}
-
-static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
-{
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- unsigned int mask;
- snd_pcm_uframes_t avail;
-
- pcm_file = file->private_data;
-
- substream = pcm_file->substream;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
-
- poll_wait(file, &runtime->sleep, wait);
-
- snd_pcm_stream_lock_irq(substream);
- avail = snd_pcm_capture_avail(runtime);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_PAUSED:
- if (avail >= runtime->control->avail_min) {
- mask = POLLIN | POLLRDNORM;
- break;
- }
- mask = 0;
- break;
- case SNDRV_PCM_STATE_DRAINING:
- if (avail > 0) {
- mask = POLLIN | POLLRDNORM;
- break;
- }
- /* Fall through */
- default:
- mask = POLLIN | POLLRDNORM | POLLERR;
- break;
- }
- snd_pcm_stream_unlock_irq(substream);
- return mask;
-}
-
-/*
- * mmap support
- */
-
-/*
- * Only on coherent architectures, we can mmap the status and the control records
- * for effcient data transfer. On others, we have to use HWSYNC ioctl...
- */
-#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
-/*
- * mmap status record
- */
-static int snd_pcm_mmap_status_fault(struct vm_area_struct *area,
- struct vm_fault *vmf)
-{
- struct snd_pcm_substream *substream = area->vm_private_data;
- struct snd_pcm_runtime *runtime;
-
- if (substream == NULL)
- return VM_FAULT_SIGBUS;
- runtime = substream->runtime;
- vmf->page = virt_to_page(runtime->status);
- get_page(vmf->page);
- return 0;
-}
-
-static const struct vm_operations_struct snd_pcm_vm_ops_status =
-{
- .fault = snd_pcm_mmap_status_fault,
-};
-
-static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
- struct vm_area_struct *area)
-{
- long size;
- if (!(area->vm_flags & VM_READ))
- return -EINVAL;
- size = area->vm_end - area->vm_start;
- if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
- return -EINVAL;
- area->vm_ops = &snd_pcm_vm_ops_status;
- area->vm_private_data = substream;
- area->vm_flags |= VM_RESERVED;
- return 0;
-}
-
-/*
- * mmap control record
- */
-static int snd_pcm_mmap_control_fault(struct vm_area_struct *area,
- struct vm_fault *vmf)
-{
- struct snd_pcm_substream *substream = area->vm_private_data;
- struct snd_pcm_runtime *runtime;
-
- if (substream == NULL)
- return VM_FAULT_SIGBUS;
- runtime = substream->runtime;
- vmf->page = virt_to_page(runtime->control);
- get_page(vmf->page);
- return 0;
-}
-
-static const struct vm_operations_struct snd_pcm_vm_ops_control =
-{
- .fault = snd_pcm_mmap_control_fault,
-};
-
-static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
- struct vm_area_struct *area)
-{
- long size;
- if (!(area->vm_flags & VM_READ))
- return -EINVAL;
- size = area->vm_end - area->vm_start;
- if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
- return -EINVAL;
- area->vm_ops = &snd_pcm_vm_ops_control;
- area->vm_private_data = substream;
- area->vm_flags |= VM_RESERVED;
- return 0;
-}
-#else /* ! coherent mmap */
-/*
- * don't support mmap for status and control records.
- */
-static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
- struct vm_area_struct *area)
-{
- return -ENXIO;
-}
-static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
- struct vm_area_struct *area)
-{
- return -ENXIO;
-}
-#endif /* coherent mmap */
-
-static inline struct page *
-snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs)
-{
- void *vaddr = substream->runtime->dma_area + ofs;
-#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
- if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
- return virt_to_page(CAC_ADDR(vaddr));
-#endif
-#if defined(CONFIG_PPC32) && defined(CONFIG_NOT_COHERENT_CACHE)
- if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) {
- dma_addr_t addr = substream->runtime->dma_addr + ofs;
- addr -= get_dma_offset(substream->dma_buffer.dev.dev);
- /* assume dma_handle set via pfn_to_phys() in
- * mm/dma-noncoherent.c
- */
- return pfn_to_page(addr >> PAGE_SHIFT);
- }
-#endif
- return virt_to_page(vaddr);
-}
-
-/*
- * fault callback for mmapping a RAM page
- */
-static int snd_pcm_mmap_data_fault(struct vm_area_struct *area,
- struct vm_fault *vmf)
-{
- struct snd_pcm_substream *substream = area->vm_private_data;
- struct snd_pcm_runtime *runtime;
- unsigned long offset;
- struct page * page;
- size_t dma_bytes;
-
- if (substream == NULL)
- return VM_FAULT_SIGBUS;
- runtime = substream->runtime;
- offset = vmf->pgoff << PAGE_SHIFT;
- dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
- if (offset > dma_bytes - PAGE_SIZE)
- return VM_FAULT_SIGBUS;
- if (substream->ops->page)
- page = substream->ops->page(substream, offset);
- else
- page = snd_pcm_default_page_ops(substream, offset);
- if (!page)
- return VM_FAULT_SIGBUS;
- get_page(page);
- vmf->page = page;
- return 0;
-}
-
-static const struct vm_operations_struct snd_pcm_vm_ops_data = {
- .open = snd_pcm_mmap_data_open,
- .close = snd_pcm_mmap_data_close,
-};
-
-static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = {
- .open = snd_pcm_mmap_data_open,
- .close = snd_pcm_mmap_data_close,
- .fault = snd_pcm_mmap_data_fault,
-};
-
-#ifndef ARCH_HAS_DMA_MMAP_COHERENT
-/* This should be defined / handled globally! */
-#ifdef CONFIG_ARM
-#define ARCH_HAS_DMA_MMAP_COHERENT
-#endif
-#endif
-
-/*
- * mmap the DMA buffer on RAM
- */
-int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *area)
-{
- area->vm_flags |= VM_RESERVED;
-#ifdef ARCH_HAS_DMA_MMAP_COHERENT
- if (!substream->ops->page &&
- substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
- return dma_mmap_coherent(substream->dma_buffer.dev.dev,
- area,
- substream->runtime->dma_area,
- substream->runtime->dma_addr,
- area->vm_end - area->vm_start);
-#elif defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
- if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV &&
- !plat_device_is_coherent(substream->dma_buffer.dev.dev))
- area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
-#endif /* ARCH_HAS_DMA_MMAP_COHERENT */
- /* mmap with fault handler */
- area->vm_ops = &snd_pcm_vm_ops_data_fault;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
-
-/*
- * mmap the DMA buffer on I/O memory area
- */
-#if SNDRV_PCM_INFO_MMAP_IOMEM
-int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
- struct vm_area_struct *area)
-{
- long size;
- unsigned long offset;
-
- area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
- area->vm_flags |= VM_IO;
- size = area->vm_end - area->vm_start;
- offset = area->vm_pgoff << PAGE_SHIFT;
- if (io_remap_pfn_range(area, area->vm_start,
- (substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
- size, area->vm_page_prot))
- return -EAGAIN;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
-#endif /* SNDRV_PCM_INFO_MMAP */
-
-/*
- * mmap DMA buffer
- */
-int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
- struct vm_area_struct *area)
-{
- struct snd_pcm_runtime *runtime;
- long size;
- unsigned long offset;
- size_t dma_bytes;
- int err;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if (!(area->vm_flags & (VM_WRITE|VM_READ)))
- return -EINVAL;
- } else {
- if (!(area->vm_flags & VM_READ))
- return -EINVAL;
- }
- runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (!(runtime->info & SNDRV_PCM_INFO_MMAP))
- return -ENXIO;
- if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
- runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
- return -EINVAL;
- size = area->vm_end - area->vm_start;
- offset = area->vm_pgoff << PAGE_SHIFT;
- dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
- if ((size_t)size > dma_bytes)
- return -EINVAL;
- if (offset > dma_bytes - size)
- return -EINVAL;
-
- area->vm_ops = &snd_pcm_vm_ops_data;
- area->vm_private_data = substream;
- if (substream->ops->mmap)
- err = substream->ops->mmap(substream, area);
- else
- err = snd_pcm_lib_default_mmap(substream, area);
- if (!err)
- atomic_inc(&substream->mmap_count);
- return err;
-}
-
-EXPORT_SYMBOL(snd_pcm_mmap_data);
-
-static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
-{
- struct snd_pcm_file * pcm_file;
- struct snd_pcm_substream *substream;
- unsigned long offset;
-
- pcm_file = file->private_data;
- substream = pcm_file->substream;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
-
- offset = area->vm_pgoff << PAGE_SHIFT;
- switch (offset) {
- case SNDRV_PCM_MMAP_OFFSET_STATUS:
- if (pcm_file->no_compat_mmap)
- return -ENXIO;
- return snd_pcm_mmap_status(substream, file, area);
- case SNDRV_PCM_MMAP_OFFSET_CONTROL:
- if (pcm_file->no_compat_mmap)
- return -ENXIO;
- return snd_pcm_mmap_control(substream, file, area);
- default:
- return snd_pcm_mmap_data(substream, file, area);
- }
- return 0;
-}
-
-static int snd_pcm_fasync(int fd, struct file * file, int on)
-{
- struct snd_pcm_file * pcm_file;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
-
- pcm_file = file->private_data;
- substream = pcm_file->substream;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- return fasync_helper(fd, file, on, &runtime->fasync);
-}
-
-/*
- * ioctl32 compat
- */
-#ifdef CONFIG_COMPAT
-#include "pcm_compat.c"
-#else
-#define snd_pcm_ioctl_compat NULL
-#endif
-
-/*
- * To be removed helpers to keep binary compatibility
- */
-
-#ifdef CONFIG_SND_SUPPORT_OLD_API
-#define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
-#define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
-
-static void snd_pcm_hw_convert_from_old_params(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_params_old *oparams)
-{
- unsigned int i;
-
- memset(params, 0, sizeof(*params));
- params->flags = oparams->flags;
- for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
- params->masks[i].bits[0] = oparams->masks[i];
- memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
- params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
- params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
- params->info = oparams->info;
- params->msbits = oparams->msbits;
- params->rate_num = oparams->rate_num;
- params->rate_den = oparams->rate_den;
- params->fifo_size = oparams->fifo_size;
-}
-
-static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *oparams,
- struct snd_pcm_hw_params *params)
-{
- unsigned int i;
-
- memset(oparams, 0, sizeof(*oparams));
- oparams->flags = params->flags;
- for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
- oparams->masks[i] = params->masks[i].bits[0];
- memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
- oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
- oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
- oparams->info = params->info;
- oparams->msbits = params->msbits;
- oparams->rate_num = params->rate_num;
- oparams->rate_den = params->rate_den;
- oparams->fifo_size = params->fifo_size;
-}
-
-static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params_old __user * _oparams)
-{
- struct snd_pcm_hw_params *params;
- struct snd_pcm_hw_params_old *oparams = NULL;
- int err;
-
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params)
- return -ENOMEM;
-
- oparams = memdup_user(_oparams, sizeof(*oparams));
- if (IS_ERR(oparams)) {
- err = PTR_ERR(oparams);
- goto out;
- }
- snd_pcm_hw_convert_from_old_params(params, oparams);
- err = snd_pcm_hw_refine(substream, params);
- snd_pcm_hw_convert_to_old_params(oparams, params);
- if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
- if (!err)
- err = -EFAULT;
- }
-
- kfree(oparams);
-out:
- kfree(params);
- return err;
-}
-
-static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params_old __user * _oparams)
-{
- struct snd_pcm_hw_params *params;
- struct snd_pcm_hw_params_old *oparams = NULL;
- int err;
-
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params)
- return -ENOMEM;
-
- oparams = memdup_user(_oparams, sizeof(*oparams));
- if (IS_ERR(oparams)) {
- err = PTR_ERR(oparams);
- goto out;
- }
- snd_pcm_hw_convert_from_old_params(params, oparams);
- err = snd_pcm_hw_params(substream, params);
- snd_pcm_hw_convert_to_old_params(oparams, params);
- if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
- if (!err)
- err = -EFAULT;
- }
-
- kfree(oparams);
-out:
- kfree(params);
- return err;
-}
-#endif /* CONFIG_SND_SUPPORT_OLD_API */
-
-#ifndef CONFIG_MMU
-static unsigned long snd_pcm_get_unmapped_area(struct file *file,
- unsigned long addr,
- unsigned long len,
- unsigned long pgoff,
- unsigned long flags)
-{
- struct snd_pcm_file *pcm_file = file->private_data;
- struct snd_pcm_substream *substream = pcm_file->substream;
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long offset = pgoff << PAGE_SHIFT;
-
- switch (offset) {
- case SNDRV_PCM_MMAP_OFFSET_STATUS:
- return (unsigned long)runtime->status;
- case SNDRV_PCM_MMAP_OFFSET_CONTROL:
- return (unsigned long)runtime->control;
- default:
- return (unsigned long)runtime->dma_area + offset;
- }
-}
-#else
-# define snd_pcm_get_unmapped_area NULL
-#endif
-
-/*
- * Register section
- */
-
-const struct file_operations snd_pcm_f_ops[2] = {
- {
- .owner = THIS_MODULE,
- .write = snd_pcm_write,
- .aio_write = snd_pcm_aio_write,
- .open = snd_pcm_playback_open,
- .release = snd_pcm_release,
- .llseek = no_llseek,
- .poll = snd_pcm_playback_poll,
- .unlocked_ioctl = snd_pcm_playback_ioctl,
- .compat_ioctl = snd_pcm_ioctl_compat,
- .mmap = snd_pcm_mmap,
- .fasync = snd_pcm_fasync,
- .get_unmapped_area = snd_pcm_get_unmapped_area,
- },
- {
- .owner = THIS_MODULE,
- .read = snd_pcm_read,
- .aio_read = snd_pcm_aio_read,
- .open = snd_pcm_capture_open,
- .release = snd_pcm_release,
- .llseek = no_llseek,
- .poll = snd_pcm_capture_poll,
- .unlocked_ioctl = snd_pcm_capture_ioctl,
- .compat_ioctl = snd_pcm_ioctl_compat,
- .mmap = snd_pcm_mmap,
- .fasync = snd_pcm_fasync,
- .get_unmapped_area = snd_pcm_get_unmapped_area,
- }
-};
diff --git a/ANDROID_3.4.5/sound/core/pcm_timer.c b/ANDROID_3.4.5/sound/core/pcm_timer.c
deleted file mode 100644
index b01d9481..00000000
--- a/ANDROID_3.4.5/sound/core/pcm_timer.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/time.h>
-#include <linux/gcd.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/timer.h>
-
-/*
- * Timer functions
- */
-
-void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
-{
- unsigned long rate, mult, fsize, l, post;
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- mult = 1000000000;
- rate = runtime->rate;
- if (snd_BUG_ON(!rate))
- return;
- l = gcd(mult, rate);
- mult /= l;
- rate /= l;
- fsize = runtime->period_size;
- if (snd_BUG_ON(!fsize))
- return;
- l = gcd(rate, fsize);
- rate /= l;
- fsize /= l;
- post = 1;
- while ((mult * fsize) / fsize != mult) {
- mult /= 2;
- post *= 2;
- }
- if (rate == 0) {
- snd_printk(KERN_ERR "pcm timer resolution out of range (rate = %u, period_size = %lu)\n", runtime->rate, runtime->period_size);
- runtime->timer_resolution = -1;
- return;
- }
- runtime->timer_resolution = (mult * fsize / rate) * post;
-}
-
-static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
-{
- struct snd_pcm_substream *substream;
-
- substream = timer->private_data;
- return substream->runtime ? substream->runtime->timer_resolution : 0;
-}
-
-static int snd_pcm_timer_start(struct snd_timer * timer)
-{
- struct snd_pcm_substream *substream;
-
- substream = snd_timer_chip(timer);
- substream->timer_running = 1;
- return 0;
-}
-
-static int snd_pcm_timer_stop(struct snd_timer * timer)
-{
- struct snd_pcm_substream *substream;
-
- substream = snd_timer_chip(timer);
- substream->timer_running = 0;
- return 0;
-}
-
-static struct snd_timer_hardware snd_pcm_timer =
-{
- .flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_SLAVE,
- .resolution = 0,
- .ticks = 1,
- .c_resolution = snd_pcm_timer_resolution,
- .start = snd_pcm_timer_start,
- .stop = snd_pcm_timer_stop,
-};
-
-/*
- * Init functions
- */
-
-static void snd_pcm_timer_free(struct snd_timer *timer)
-{
- struct snd_pcm_substream *substream = timer->private_data;
- substream->timer = NULL;
-}
-
-void snd_pcm_timer_init(struct snd_pcm_substream *substream)
-{
- struct snd_timer_id tid;
- struct snd_timer *timer;
-
- tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
- tid.dev_class = SNDRV_TIMER_CLASS_PCM;
- tid.card = substream->pcm->card->number;
- tid.device = substream->pcm->device;
- tid.subdevice = (substream->number << 1) | (substream->stream & 1);
- if (snd_timer_new(substream->pcm->card, "PCM", &tid, &timer) < 0)
- return;
- sprintf(timer->name, "PCM %s %i-%i-%i",
- substream->stream == SNDRV_PCM_STREAM_CAPTURE ?
- "capture" : "playback",
- tid.card, tid.device, tid.subdevice);
- timer->hw = snd_pcm_timer;
- if (snd_device_register(timer->card, timer) < 0) {
- snd_device_free(timer->card, timer);
- return;
- }
- timer->private_data = substream;
- timer->private_free = snd_pcm_timer_free;
- substream->timer = timer;
-}
-
-void snd_pcm_timer_done(struct snd_pcm_substream *substream)
-{
- if (substream->timer) {
- snd_device_free(substream->pcm->card, substream->timer);
- substream->timer = NULL;
- }
-}
diff --git a/ANDROID_3.4.5/sound/core/rawmidi.c b/ANDROID_3.4.5/sound/core/rawmidi.c
deleted file mode 100644
index 1bb95aee..00000000
--- a/ANDROID_3.4.5/sound/core/rawmidi.c
+++ /dev/null
@@ -1,1726 +0,0 @@
-/*
- * Abstract layer for MIDI v1.0 stream
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <sound/core.h>
-#include <linux/major.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <sound/rawmidi.h>
-#include <sound/info.h>
-#include <sound/control.h>
-#include <sound/minors.h>
-#include <sound/initval.h>
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA.");
-MODULE_LICENSE("GPL");
-
-#ifdef CONFIG_SND_OSSEMUL
-static int midi_map[SNDRV_CARDS];
-static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
-module_param_array(midi_map, int, NULL, 0444);
-MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device.");
-module_param_array(amidi_map, int, NULL, 0444);
-MODULE_PARM_DESC(amidi_map, "Raw MIDI device number assigned to 2nd OSS device.");
-#endif /* CONFIG_SND_OSSEMUL */
-
-static int snd_rawmidi_free(struct snd_rawmidi *rawmidi);
-static int snd_rawmidi_dev_free(struct snd_device *device);
-static int snd_rawmidi_dev_register(struct snd_device *device);
-static int snd_rawmidi_dev_disconnect(struct snd_device *device);
-
-static LIST_HEAD(snd_rawmidi_devices);
-static DEFINE_MUTEX(register_mutex);
-
-static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
-{
- struct snd_rawmidi *rawmidi;
-
- list_for_each_entry(rawmidi, &snd_rawmidi_devices, list)
- if (rawmidi->card == card && rawmidi->device == device)
- return rawmidi;
- return NULL;
-}
-
-static inline unsigned short snd_rawmidi_file_flags(struct file *file)
-{
- switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
- case FMODE_WRITE:
- return SNDRV_RAWMIDI_LFLG_OUTPUT;
- case FMODE_READ:
- return SNDRV_RAWMIDI_LFLG_INPUT;
- default:
- return SNDRV_RAWMIDI_LFLG_OPEN;
- }
-}
-
-static inline int snd_rawmidi_ready(struct snd_rawmidi_substream *substream)
-{
- struct snd_rawmidi_runtime *runtime = substream->runtime;
- return runtime->avail >= runtime->avail_min;
-}
-
-static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substream,
- size_t count)
-{
- struct snd_rawmidi_runtime *runtime = substream->runtime;
- return runtime->avail >= runtime->avail_min &&
- (!substream->append || runtime->avail >= count);
-}
-
-static void snd_rawmidi_input_event_work(struct work_struct *work)
-{
- struct snd_rawmidi_runtime *runtime =
- container_of(work, struct snd_rawmidi_runtime, event_work);
- if (runtime->event)
- runtime->event(runtime->substream);
-}
-
-static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
-{
- struct snd_rawmidi_runtime *runtime;
-
- if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)
- return -ENOMEM;
- runtime->substream = substream;
- spin_lock_init(&runtime->lock);
- init_waitqueue_head(&runtime->sleep);
- INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work);
- runtime->event = NULL;
- runtime->buffer_size = PAGE_SIZE;
- runtime->avail_min = 1;
- if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
- runtime->avail = 0;
- else
- runtime->avail = runtime->buffer_size;
- if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) {
- kfree(runtime);
- return -ENOMEM;
- }
- runtime->appl_ptr = runtime->hw_ptr = 0;
- substream->runtime = runtime;
- return 0;
-}
-
-static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream)
-{
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- kfree(runtime->buffer);
- kfree(runtime);
- substream->runtime = NULL;
- return 0;
-}
-
-static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up)
-{
- if (!substream->opened)
- return;
- substream->ops->trigger(substream, up);
-}
-
-static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
-{
- if (!substream->opened)
- return;
- substream->ops->trigger(substream, up);
- if (!up)
- cancel_work_sync(&substream->runtime->event_work);
-}
-
-int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream)
-{
- unsigned long flags;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- snd_rawmidi_output_trigger(substream, 0);
- runtime->drain = 0;
- spin_lock_irqsave(&runtime->lock, flags);
- runtime->appl_ptr = runtime->hw_ptr = 0;
- runtime->avail = runtime->buffer_size;
- spin_unlock_irqrestore(&runtime->lock, flags);
- return 0;
-}
-
-int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream)
-{
- int err;
- long timeout;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- err = 0;
- runtime->drain = 1;
- timeout = wait_event_interruptible_timeout(runtime->sleep,
- (runtime->avail >= runtime->buffer_size),
- 10*HZ);
- if (signal_pending(current))
- err = -ERESTARTSYS;
- if (runtime->avail < runtime->buffer_size && !timeout) {
- snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size);
- err = -EIO;
- }
- runtime->drain = 0;
- if (err != -ERESTARTSYS) {
- /* we need wait a while to make sure that Tx FIFOs are empty */
- if (substream->ops->drain)
- substream->ops->drain(substream);
- else
- msleep(50);
- snd_rawmidi_drop_output(substream);
- }
- return err;
-}
-
-int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)
-{
- unsigned long flags;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- snd_rawmidi_input_trigger(substream, 0);
- runtime->drain = 0;
- spin_lock_irqsave(&runtime->lock, flags);
- runtime->appl_ptr = runtime->hw_ptr = 0;
- runtime->avail = 0;
- spin_unlock_irqrestore(&runtime->lock, flags);
- return 0;
-}
-
-/* look for an available substream for the given stream direction;
- * if a specific subdevice is given, try to assign it
- */
-static int assign_substream(struct snd_rawmidi *rmidi, int subdevice,
- int stream, int mode,
- struct snd_rawmidi_substream **sub_ret)
-{
- struct snd_rawmidi_substream *substream;
- struct snd_rawmidi_str *s = &rmidi->streams[stream];
- static unsigned int info_flags[2] = {
- [SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT,
- [SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT,
- };
-
- if (!(rmidi->info_flags & info_flags[stream]))
- return -ENXIO;
- if (subdevice >= 0 && subdevice >= s->substream_count)
- return -ENODEV;
-
- list_for_each_entry(substream, &s->substreams, list) {
- if (substream->opened) {
- if (stream == SNDRV_RAWMIDI_STREAM_INPUT ||
- !(mode & SNDRV_RAWMIDI_LFLG_APPEND) ||
- !substream->append)
- continue;
- }
- if (subdevice < 0 || subdevice == substream->number) {
- *sub_ret = substream;
- return 0;
- }
- }
- return -EAGAIN;
-}
-
-/* open and do ref-counting for the given substream */
-static int open_substream(struct snd_rawmidi *rmidi,
- struct snd_rawmidi_substream *substream,
- int mode)
-{
- int err;
-
- if (substream->use_count == 0) {
- err = snd_rawmidi_runtime_create(substream);
- if (err < 0)
- return err;
- err = substream->ops->open(substream);
- if (err < 0) {
- snd_rawmidi_runtime_free(substream);
- return err;
- }
- substream->opened = 1;
- substream->active_sensing = 0;
- if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
- substream->append = 1;
- substream->pid = get_pid(task_pid(current));
- rmidi->streams[substream->stream].substream_opened++;
- }
- substream->use_count++;
- return 0;
-}
-
-static void close_substream(struct snd_rawmidi *rmidi,
- struct snd_rawmidi_substream *substream,
- int cleanup);
-
-static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
- struct snd_rawmidi_file *rfile)
-{
- struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL;
- int err;
-
- rfile->input = rfile->output = NULL;
- if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
- err = assign_substream(rmidi, subdevice,
- SNDRV_RAWMIDI_STREAM_INPUT,
- mode, &sinput);
- if (err < 0)
- return err;
- }
- if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
- err = assign_substream(rmidi, subdevice,
- SNDRV_RAWMIDI_STREAM_OUTPUT,
- mode, &soutput);
- if (err < 0)
- return err;
- }
-
- if (sinput) {
- err = open_substream(rmidi, sinput, mode);
- if (err < 0)
- return err;
- }
- if (soutput) {
- err = open_substream(rmidi, soutput, mode);
- if (err < 0) {
- if (sinput)
- close_substream(rmidi, sinput, 0);
- return err;
- }
- }
-
- rfile->rmidi = rmidi;
- rfile->input = sinput;
- rfile->output = soutput;
- return 0;
-}
-
-/* called from sound/core/seq/seq_midi.c */
-int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
- int mode, struct snd_rawmidi_file * rfile)
-{
- struct snd_rawmidi *rmidi;
- int err;
-
- if (snd_BUG_ON(!rfile))
- return -EINVAL;
-
- mutex_lock(&register_mutex);
- rmidi = snd_rawmidi_search(card, device);
- if (rmidi == NULL) {
- mutex_unlock(&register_mutex);
- return -ENODEV;
- }
- if (!try_module_get(rmidi->card->module)) {
- mutex_unlock(&register_mutex);
- return -ENXIO;
- }
- mutex_unlock(&register_mutex);
-
- mutex_lock(&rmidi->open_mutex);
- err = rawmidi_open_priv(rmidi, subdevice, mode, rfile);
- mutex_unlock(&rmidi->open_mutex);
- if (err < 0)
- module_put(rmidi->card->module);
- return err;
-}
-
-static int snd_rawmidi_open(struct inode *inode, struct file *file)
-{
- int maj = imajor(inode);
- struct snd_card *card;
- int subdevice;
- unsigned short fflags;
- int err;
- struct snd_rawmidi *rmidi;
- struct snd_rawmidi_file *rawmidi_file = NULL;
- wait_queue_t wait;
- struct snd_ctl_file *kctl;
-
- if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
- return -EINVAL; /* invalid combination */
-
- err = nonseekable_open(inode, file);
- if (err < 0)
- return err;
-
- if (maj == snd_major) {
- rmidi = snd_lookup_minor_data(iminor(inode),
- SNDRV_DEVICE_TYPE_RAWMIDI);
-#ifdef CONFIG_SND_OSSEMUL
- } else if (maj == SOUND_MAJOR) {
- rmidi = snd_lookup_oss_minor_data(iminor(inode),
- SNDRV_OSS_DEVICE_TYPE_MIDI);
-#endif
- } else
- return -ENXIO;
-
- if (rmidi == NULL)
- return -ENODEV;
-
- if (!try_module_get(rmidi->card->module)) {
- snd_card_unref(rmidi->card);
- return -ENXIO;
- }
-
- mutex_lock(&rmidi->open_mutex);
- card = rmidi->card;
- err = snd_card_file_add(card, file);
- if (err < 0)
- goto __error_card;
- fflags = snd_rawmidi_file_flags(file);
- if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */
- fflags |= SNDRV_RAWMIDI_LFLG_APPEND;
- rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL);
- if (rawmidi_file == NULL) {
- err = -ENOMEM;
- goto __error;
- }
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&rmidi->open_wait, &wait);
- while (1) {
- subdevice = -1;
- read_lock(&card->ctl_files_rwlock);
- list_for_each_entry(kctl, &card->ctl_files, list) {
- if (kctl->pid == task_pid(current)) {
- subdevice = kctl->prefer_rawmidi_subdevice;
- if (subdevice != -1)
- break;
- }
- }
- read_unlock(&card->ctl_files_rwlock);
- err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file);
- if (err >= 0)
- break;
- if (err == -EAGAIN) {
- if (file->f_flags & O_NONBLOCK) {
- err = -EBUSY;
- break;
- }
- } else
- break;
- set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&rmidi->open_mutex);
- schedule();
- mutex_lock(&rmidi->open_mutex);
- if (rmidi->card->shutdown) {
- err = -ENODEV;
- break;
- }
- if (signal_pending(current)) {
- err = -ERESTARTSYS;
- break;
- }
- }
- remove_wait_queue(&rmidi->open_wait, &wait);
- if (err < 0) {
- kfree(rawmidi_file);
- goto __error;
- }
-#ifdef CONFIG_SND_OSSEMUL
- if (rawmidi_file->input && rawmidi_file->input->runtime)
- rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR);
- if (rawmidi_file->output && rawmidi_file->output->runtime)
- rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR);
-#endif
- file->private_data = rawmidi_file;
- mutex_unlock(&rmidi->open_mutex);
- snd_card_unref(rmidi->card);
- return 0;
-
- __error:
- snd_card_file_remove(card, file);
- __error_card:
- mutex_unlock(&rmidi->open_mutex);
- module_put(rmidi->card->module);
- snd_card_unref(rmidi->card);
- return err;
-}
-
-static void close_substream(struct snd_rawmidi *rmidi,
- struct snd_rawmidi_substream *substream,
- int cleanup)
-{
- if (--substream->use_count)
- return;
-
- if (cleanup) {
- if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
- snd_rawmidi_input_trigger(substream, 0);
- else {
- if (substream->active_sensing) {
- unsigned char buf = 0xfe;
- /* sending single active sensing message
- * to shut the device up
- */
- snd_rawmidi_kernel_write(substream, &buf, 1);
- }
- if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS)
- snd_rawmidi_output_trigger(substream, 0);
- }
- }
- substream->ops->close(substream);
- if (substream->runtime->private_free)
- substream->runtime->private_free(substream);
- snd_rawmidi_runtime_free(substream);
- substream->opened = 0;
- substream->append = 0;
- put_pid(substream->pid);
- substream->pid = NULL;
- rmidi->streams[substream->stream].substream_opened--;
-}
-
-static void rawmidi_release_priv(struct snd_rawmidi_file *rfile)
-{
- struct snd_rawmidi *rmidi;
-
- rmidi = rfile->rmidi;
- mutex_lock(&rmidi->open_mutex);
- if (rfile->input) {
- close_substream(rmidi, rfile->input, 1);
- rfile->input = NULL;
- }
- if (rfile->output) {
- close_substream(rmidi, rfile->output, 1);
- rfile->output = NULL;
- }
- rfile->rmidi = NULL;
- mutex_unlock(&rmidi->open_mutex);
- wake_up(&rmidi->open_wait);
-}
-
-/* called from sound/core/seq/seq_midi.c */
-int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile)
-{
- struct snd_rawmidi *rmidi;
-
- if (snd_BUG_ON(!rfile))
- return -ENXIO;
-
- rmidi = rfile->rmidi;
- rawmidi_release_priv(rfile);
- module_put(rmidi->card->module);
- return 0;
-}
-
-static int snd_rawmidi_release(struct inode *inode, struct file *file)
-{
- struct snd_rawmidi_file *rfile;
- struct snd_rawmidi *rmidi;
- struct module *module;
-
- rfile = file->private_data;
- rmidi = rfile->rmidi;
- rawmidi_release_priv(rfile);
- kfree(rfile);
- module = rmidi->card->module;
- snd_card_file_remove(rmidi->card, file);
- module_put(module);
- return 0;
-}
-
-static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_info *info)
-{
- struct snd_rawmidi *rmidi;
-
- if (substream == NULL)
- return -ENODEV;
- rmidi = substream->rmidi;
- memset(info, 0, sizeof(*info));
- info->card = rmidi->card->number;
- info->device = rmidi->device;
- info->subdevice = substream->number;
- info->stream = substream->stream;
- info->flags = rmidi->info_flags;
- strcpy(info->id, rmidi->id);
- strcpy(info->name, rmidi->name);
- strcpy(info->subname, substream->name);
- info->subdevices_count = substream->pstr->substream_count;
- info->subdevices_avail = (substream->pstr->substream_count -
- substream->pstr->substream_opened);
- return 0;
-}
-
-static int snd_rawmidi_info_user(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_info __user * _info)
-{
- struct snd_rawmidi_info info;
- int err;
- if ((err = snd_rawmidi_info(substream, &info)) < 0)
- return err;
- if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info)))
- return -EFAULT;
- return 0;
-}
-
-int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info)
-{
- struct snd_rawmidi *rmidi;
- struct snd_rawmidi_str *pstr;
- struct snd_rawmidi_substream *substream;
-
- mutex_lock(&register_mutex);
- rmidi = snd_rawmidi_search(card, info->device);
- mutex_unlock(&register_mutex);
- if (!rmidi)
- return -ENXIO;
- if (info->stream < 0 || info->stream > 1)
- return -EINVAL;
- pstr = &rmidi->streams[info->stream];
- if (pstr->substream_count == 0)
- return -ENOENT;
- if (info->subdevice >= pstr->substream_count)
- return -ENXIO;
- list_for_each_entry(substream, &pstr->substreams, list) {
- if ((unsigned int)substream->number == info->subdevice)
- return snd_rawmidi_info(substream, info);
- }
- return -ENXIO;
-}
-
-static int snd_rawmidi_info_select_user(struct snd_card *card,
- struct snd_rawmidi_info __user *_info)
-{
- int err;
- struct snd_rawmidi_info info;
- if (get_user(info.device, &_info->device))
- return -EFAULT;
- if (get_user(info.stream, &_info->stream))
- return -EFAULT;
- if (get_user(info.subdevice, &_info->subdevice))
- return -EFAULT;
- if ((err = snd_rawmidi_info_select(card, &info)) < 0)
- return err;
- if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info)))
- return -EFAULT;
- return 0;
-}
-
-int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_params * params)
-{
- char *newbuf;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- if (substream->append && substream->use_count > 1)
- return -EBUSY;
- snd_rawmidi_drain_output(substream);
- if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) {
- return -EINVAL;
- }
- if (params->avail_min < 1 || params->avail_min > params->buffer_size) {
- return -EINVAL;
- }
- if (params->buffer_size != runtime->buffer_size) {
- newbuf = krealloc(runtime->buffer, params->buffer_size,
- GFP_KERNEL);
- if (!newbuf)
- return -ENOMEM;
- runtime->buffer = newbuf;
- runtime->buffer_size = params->buffer_size;
- runtime->avail = runtime->buffer_size;
- }
- runtime->avail_min = params->avail_min;
- substream->active_sensing = !params->no_active_sensing;
- return 0;
-}
-
-int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_params * params)
-{
- char *newbuf;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- snd_rawmidi_drain_input(substream);
- if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) {
- return -EINVAL;
- }
- if (params->avail_min < 1 || params->avail_min > params->buffer_size) {
- return -EINVAL;
- }
- if (params->buffer_size != runtime->buffer_size) {
- newbuf = krealloc(runtime->buffer, params->buffer_size,
- GFP_KERNEL);
- if (!newbuf)
- return -ENOMEM;
- runtime->buffer = newbuf;
- runtime->buffer_size = params->buffer_size;
- }
- runtime->avail_min = params->avail_min;
- return 0;
-}
-
-static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_status * status)
-{
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- memset(status, 0, sizeof(*status));
- status->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
- spin_lock_irq(&runtime->lock);
- status->avail = runtime->avail;
- spin_unlock_irq(&runtime->lock);
- return 0;
-}
-
-static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_status * status)
-{
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- memset(status, 0, sizeof(*status));
- status->stream = SNDRV_RAWMIDI_STREAM_INPUT;
- spin_lock_irq(&runtime->lock);
- status->avail = runtime->avail;
- status->xruns = runtime->xruns;
- runtime->xruns = 0;
- spin_unlock_irq(&runtime->lock);
- return 0;
-}
-
-static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct snd_rawmidi_file *rfile;
- void __user *argp = (void __user *)arg;
-
- rfile = file->private_data;
- if (((cmd >> 8) & 0xff) != 'W')
- return -ENOTTY;
- switch (cmd) {
- case SNDRV_RAWMIDI_IOCTL_PVERSION:
- return put_user(SNDRV_RAWMIDI_VERSION, (int __user *)argp) ? -EFAULT : 0;
- case SNDRV_RAWMIDI_IOCTL_INFO:
- {
- int stream;
- struct snd_rawmidi_info __user *info = argp;
- if (get_user(stream, &info->stream))
- return -EFAULT;
- switch (stream) {
- case SNDRV_RAWMIDI_STREAM_INPUT:
- return snd_rawmidi_info_user(rfile->input, info);
- case SNDRV_RAWMIDI_STREAM_OUTPUT:
- return snd_rawmidi_info_user(rfile->output, info);
- default:
- return -EINVAL;
- }
- }
- case SNDRV_RAWMIDI_IOCTL_PARAMS:
- {
- struct snd_rawmidi_params params;
- if (copy_from_user(&params, argp, sizeof(struct snd_rawmidi_params)))
- return -EFAULT;
- switch (params.stream) {
- case SNDRV_RAWMIDI_STREAM_OUTPUT:
- if (rfile->output == NULL)
- return -EINVAL;
- return snd_rawmidi_output_params(rfile->output, &params);
- case SNDRV_RAWMIDI_STREAM_INPUT:
- if (rfile->input == NULL)
- return -EINVAL;
- return snd_rawmidi_input_params(rfile->input, &params);
- default:
- return -EINVAL;
- }
- }
- case SNDRV_RAWMIDI_IOCTL_STATUS:
- {
- int err = 0;
- struct snd_rawmidi_status status;
- if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status)))
- return -EFAULT;
- switch (status.stream) {
- case SNDRV_RAWMIDI_STREAM_OUTPUT:
- if (rfile->output == NULL)
- return -EINVAL;
- err = snd_rawmidi_output_status(rfile->output, &status);
- break;
- case SNDRV_RAWMIDI_STREAM_INPUT:
- if (rfile->input == NULL)
- return -EINVAL;
- err = snd_rawmidi_input_status(rfile->input, &status);
- break;
- default:
- return -EINVAL;
- }
- if (err < 0)
- return err;
- if (copy_to_user(argp, &status, sizeof(struct snd_rawmidi_status)))
- return -EFAULT;
- return 0;
- }
- case SNDRV_RAWMIDI_IOCTL_DROP:
- {
- int val;
- if (get_user(val, (int __user *) argp))
- return -EFAULT;
- switch (val) {
- case SNDRV_RAWMIDI_STREAM_OUTPUT:
- if (rfile->output == NULL)
- return -EINVAL;
- return snd_rawmidi_drop_output(rfile->output);
- default:
- return -EINVAL;
- }
- }
- case SNDRV_RAWMIDI_IOCTL_DRAIN:
- {
- int val;
- if (get_user(val, (int __user *) argp))
- return -EFAULT;
- switch (val) {
- case SNDRV_RAWMIDI_STREAM_OUTPUT:
- if (rfile->output == NULL)
- return -EINVAL;
- return snd_rawmidi_drain_output(rfile->output);
- case SNDRV_RAWMIDI_STREAM_INPUT:
- if (rfile->input == NULL)
- return -EINVAL;
- return snd_rawmidi_drain_input(rfile->input);
- default:
- return -EINVAL;
- }
- }
-#ifdef CONFIG_SND_DEBUG
- default:
- snd_printk(KERN_WARNING "rawmidi: unknown command = 0x%x\n", cmd);
-#endif
- }
- return -ENOTTY;
-}
-
-static int snd_rawmidi_control_ioctl(struct snd_card *card,
- struct snd_ctl_file *control,
- unsigned int cmd,
- unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
- case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
- {
- int device;
-
- if (get_user(device, (int __user *)argp))
- return -EFAULT;
- if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */
- device = SNDRV_RAWMIDI_DEVICES - 1;
- mutex_lock(&register_mutex);
- device = device < 0 ? 0 : device + 1;
- while (device < SNDRV_RAWMIDI_DEVICES) {
- if (snd_rawmidi_search(card, device))
- break;
- device++;
- }
- if (device == SNDRV_RAWMIDI_DEVICES)
- device = -1;
- mutex_unlock(&register_mutex);
- if (put_user(device, (int __user *)argp))
- return -EFAULT;
- return 0;
- }
- case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE:
- {
- int val;
-
- if (get_user(val, (int __user *)argp))
- return -EFAULT;
- control->prefer_rawmidi_subdevice = val;
- return 0;
- }
- case SNDRV_CTL_IOCTL_RAWMIDI_INFO:
- return snd_rawmidi_info_select_user(card, argp);
- }
- return -ENOIOCTLCMD;
-}
-
-/**
- * snd_rawmidi_receive - receive the input data from the device
- * @substream: the rawmidi substream
- * @buffer: the buffer pointer
- * @count: the data size to read
- *
- * Reads the data from the internal buffer.
- *
- * Returns the size of read data, or a negative error code on failure.
- */
-int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
- const unsigned char *buffer, int count)
-{
- unsigned long flags;
- int result = 0, count1;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- if (!substream->opened)
- return -EBADFD;
- if (runtime->buffer == NULL) {
- snd_printd("snd_rawmidi_receive: input is not active!!!\n");
- return -EINVAL;
- }
- spin_lock_irqsave(&runtime->lock, flags);
- if (count == 1) { /* special case, faster code */
- substream->bytes++;
- if (runtime->avail < runtime->buffer_size) {
- runtime->buffer[runtime->hw_ptr++] = buffer[0];
- runtime->hw_ptr %= runtime->buffer_size;
- runtime->avail++;
- result++;
- } else {
- runtime->xruns++;
- }
- } else {
- substream->bytes += count;
- count1 = runtime->buffer_size - runtime->hw_ptr;
- if (count1 > count)
- count1 = count;
- if (count1 > (int)(runtime->buffer_size - runtime->avail))
- count1 = runtime->buffer_size - runtime->avail;
- memcpy(runtime->buffer + runtime->hw_ptr, buffer, count1);
- runtime->hw_ptr += count1;
- runtime->hw_ptr %= runtime->buffer_size;
- runtime->avail += count1;
- count -= count1;
- result += count1;
- if (count > 0) {
- buffer += count1;
- count1 = count;
- if (count1 > (int)(runtime->buffer_size - runtime->avail)) {
- count1 = runtime->buffer_size - runtime->avail;
- runtime->xruns += count - count1;
- }
- if (count1 > 0) {
- memcpy(runtime->buffer, buffer, count1);
- runtime->hw_ptr = count1;
- runtime->avail += count1;
- result += count1;
- }
- }
- }
- if (result > 0) {
- if (runtime->event)
- schedule_work(&runtime->event_work);
- else if (snd_rawmidi_ready(substream))
- wake_up(&runtime->sleep);
- }
- spin_unlock_irqrestore(&runtime->lock, flags);
- return result;
-}
-
-static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
- unsigned char __user *userbuf,
- unsigned char *kernelbuf, long count)
-{
- unsigned long flags;
- long result = 0, count1;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- while (count > 0 && runtime->avail) {
- count1 = runtime->buffer_size - runtime->appl_ptr;
- if (count1 > count)
- count1 = count;
- spin_lock_irqsave(&runtime->lock, flags);
- if (count1 > (int)runtime->avail)
- count1 = runtime->avail;
- if (kernelbuf)
- memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
- if (userbuf) {
- spin_unlock_irqrestore(&runtime->lock, flags);
- if (copy_to_user(userbuf + result,
- runtime->buffer + runtime->appl_ptr, count1)) {
- return result > 0 ? result : -EFAULT;
- }
- spin_lock_irqsave(&runtime->lock, flags);
- }
- runtime->appl_ptr += count1;
- runtime->appl_ptr %= runtime->buffer_size;
- runtime->avail -= count1;
- spin_unlock_irqrestore(&runtime->lock, flags);
- result += count1;
- count -= count1;
- }
- return result;
-}
-
-long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,
- unsigned char *buf, long count)
-{
- snd_rawmidi_input_trigger(substream, 1);
- return snd_rawmidi_kernel_read1(substream, NULL/*userbuf*/, buf, count);
-}
-
-static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t count,
- loff_t *offset)
-{
- long result;
- int count1;
- struct snd_rawmidi_file *rfile;
- struct snd_rawmidi_substream *substream;
- struct snd_rawmidi_runtime *runtime;
-
- rfile = file->private_data;
- substream = rfile->input;
- if (substream == NULL)
- return -EIO;
- runtime = substream->runtime;
- snd_rawmidi_input_trigger(substream, 1);
- result = 0;
- while (count > 0) {
- spin_lock_irq(&runtime->lock);
- while (!snd_rawmidi_ready(substream)) {
- wait_queue_t wait;
- if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
- spin_unlock_irq(&runtime->lock);
- return result > 0 ? result : -EAGAIN;
- }
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&runtime->sleep, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&runtime->lock);
- schedule();
- remove_wait_queue(&runtime->sleep, &wait);
- if (rfile->rmidi->card->shutdown)
- return -ENODEV;
- if (signal_pending(current))
- return result > 0 ? result : -ERESTARTSYS;
- if (!runtime->avail)
- return result > 0 ? result : -EIO;
- spin_lock_irq(&runtime->lock);
- }
- spin_unlock_irq(&runtime->lock);
- count1 = snd_rawmidi_kernel_read1(substream,
- (unsigned char __user *)buf,
- NULL/*kernelbuf*/,
- count);
- if (count1 < 0)
- return result > 0 ? result : count1;
- result += count1;
- buf += count1;
- count -= count1;
- }
- return result;
-}
-
-/**
- * snd_rawmidi_transmit_empty - check whether the output buffer is empty
- * @substream: the rawmidi substream
- *
- * Returns 1 if the internal output buffer is empty, 0 if not.
- */
-int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
-{
- struct snd_rawmidi_runtime *runtime = substream->runtime;
- int result;
- unsigned long flags;
-
- if (runtime->buffer == NULL) {
- snd_printd("snd_rawmidi_transmit_empty: output is not active!!!\n");
- return 1;
- }
- spin_lock_irqsave(&runtime->lock, flags);
- result = runtime->avail >= runtime->buffer_size;
- spin_unlock_irqrestore(&runtime->lock, flags);
- return result;
-}
-
-/**
- * snd_rawmidi_transmit_peek - copy data from the internal buffer
- * @substream: the rawmidi substream
- * @buffer: the buffer pointer
- * @count: data size to transfer
- *
- * Copies data from the internal output buffer to the given buffer.
- *
- * Call this in the interrupt handler when the midi output is ready,
- * and call snd_rawmidi_transmit_ack() after the transmission is
- * finished.
- *
- * Returns the size of copied data, or a negative error code on failure.
- */
-int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
- unsigned char *buffer, int count)
-{
- unsigned long flags;
- int result, count1;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- if (runtime->buffer == NULL) {
- snd_printd("snd_rawmidi_transmit_peek: output is not active!!!\n");
- return -EINVAL;
- }
- result = 0;
- spin_lock_irqsave(&runtime->lock, flags);
- if (runtime->avail >= runtime->buffer_size) {
- /* warning: lowlevel layer MUST trigger down the hardware */
- goto __skip;
- }
- if (count == 1) { /* special case, faster code */
- *buffer = runtime->buffer[runtime->hw_ptr];
- result++;
- } else {
- count1 = runtime->buffer_size - runtime->hw_ptr;
- if (count1 > count)
- count1 = count;
- if (count1 > (int)(runtime->buffer_size - runtime->avail))
- count1 = runtime->buffer_size - runtime->avail;
- memcpy(buffer, runtime->buffer + runtime->hw_ptr, count1);
- count -= count1;
- result += count1;
- if (count > 0) {
- if (count > (int)(runtime->buffer_size - runtime->avail - count1))
- count = runtime->buffer_size - runtime->avail - count1;
- memcpy(buffer + count1, runtime->buffer, count);
- result += count;
- }
- }
- __skip:
- spin_unlock_irqrestore(&runtime->lock, flags);
- return result;
-}
-
-/**
- * snd_rawmidi_transmit_ack - acknowledge the transmission
- * @substream: the rawmidi substream
- * @count: the tranferred count
- *
- * Advances the hardware pointer for the internal output buffer with
- * the given size and updates the condition.
- * Call after the transmission is finished.
- *
- * Returns the advanced size if successful, or a negative error code on failure.
- */
-int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
-{
- unsigned long flags;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- if (runtime->buffer == NULL) {
- snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n");
- return -EINVAL;
- }
- spin_lock_irqsave(&runtime->lock, flags);
- snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
- runtime->hw_ptr += count;
- runtime->hw_ptr %= runtime->buffer_size;
- runtime->avail += count;
- substream->bytes += count;
- if (count > 0) {
- if (runtime->drain || snd_rawmidi_ready(substream))
- wake_up(&runtime->sleep);
- }
- spin_unlock_irqrestore(&runtime->lock, flags);
- return count;
-}
-
-/**
- * snd_rawmidi_transmit - copy from the buffer to the device
- * @substream: the rawmidi substream
- * @buffer: the buffer pointer
- * @count: the data size to transfer
- *
- * Copies data from the buffer to the device and advances the pointer.
- *
- * Returns the copied size if successful, or a negative error code on failure.
- */
-int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
- unsigned char *buffer, int count)
-{
- if (!substream->opened)
- return -EBADFD;
- count = snd_rawmidi_transmit_peek(substream, buffer, count);
- if (count < 0)
- return count;
- return snd_rawmidi_transmit_ack(substream, count);
-}
-
-static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
- const unsigned char __user *userbuf,
- const unsigned char *kernelbuf,
- long count)
-{
- unsigned long flags;
- long count1, result;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
-
- if (snd_BUG_ON(!kernelbuf && !userbuf))
- return -EINVAL;
- if (snd_BUG_ON(!runtime->buffer))
- return -EINVAL;
-
- result = 0;
- spin_lock_irqsave(&runtime->lock, flags);
- if (substream->append) {
- if ((long)runtime->avail < count) {
- spin_unlock_irqrestore(&runtime->lock, flags);
- return -EAGAIN;
- }
- }
- while (count > 0 && runtime->avail > 0) {
- count1 = runtime->buffer_size - runtime->appl_ptr;
- if (count1 > count)
- count1 = count;
- if (count1 > (long)runtime->avail)
- count1 = runtime->avail;
- if (kernelbuf)
- memcpy(runtime->buffer + runtime->appl_ptr,
- kernelbuf + result, count1);
- else if (userbuf) {
- spin_unlock_irqrestore(&runtime->lock, flags);
- if (copy_from_user(runtime->buffer + runtime->appl_ptr,
- userbuf + result, count1)) {
- spin_lock_irqsave(&runtime->lock, flags);
- result = result > 0 ? result : -EFAULT;
- goto __end;
- }
- spin_lock_irqsave(&runtime->lock, flags);
- }
- runtime->appl_ptr += count1;
- runtime->appl_ptr %= runtime->buffer_size;
- runtime->avail -= count1;
- result += count1;
- count -= count1;
- }
- __end:
- count1 = runtime->avail < runtime->buffer_size;
- spin_unlock_irqrestore(&runtime->lock, flags);
- if (count1)
- snd_rawmidi_output_trigger(substream, 1);
- return result;
-}
-
-long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream,
- const unsigned char *buf, long count)
-{
- return snd_rawmidi_kernel_write1(substream, NULL, buf, count);
-}
-
-static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
- size_t count, loff_t *offset)
-{
- long result, timeout;
- int count1;
- struct snd_rawmidi_file *rfile;
- struct snd_rawmidi_runtime *runtime;
- struct snd_rawmidi_substream *substream;
-
- rfile = file->private_data;
- substream = rfile->output;
- runtime = substream->runtime;
- /* we cannot put an atomic message to our buffer */
- if (substream->append && count > runtime->buffer_size)
- return -EIO;
- result = 0;
- while (count > 0) {
- spin_lock_irq(&runtime->lock);
- while (!snd_rawmidi_ready_append(substream, count)) {
- wait_queue_t wait;
- if (file->f_flags & O_NONBLOCK) {
- spin_unlock_irq(&runtime->lock);
- return result > 0 ? result : -EAGAIN;
- }
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&runtime->sleep, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&runtime->lock);
- timeout = schedule_timeout(30 * HZ);
- remove_wait_queue(&runtime->sleep, &wait);
- if (rfile->rmidi->card->shutdown)
- return -ENODEV;
- if (signal_pending(current))
- return result > 0 ? result : -ERESTARTSYS;
- if (!runtime->avail && !timeout)
- return result > 0 ? result : -EIO;
- spin_lock_irq(&runtime->lock);
- }
- spin_unlock_irq(&runtime->lock);
- count1 = snd_rawmidi_kernel_write1(substream, buf, NULL, count);
- if (count1 < 0)
- return result > 0 ? result : count1;
- result += count1;
- buf += count1;
- if ((size_t)count1 < count && (file->f_flags & O_NONBLOCK))
- break;
- count -= count1;
- }
- if (file->f_flags & O_DSYNC) {
- spin_lock_irq(&runtime->lock);
- while (runtime->avail != runtime->buffer_size) {
- wait_queue_t wait;
- unsigned int last_avail = runtime->avail;
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&runtime->sleep, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&runtime->lock);
- timeout = schedule_timeout(30 * HZ);
- remove_wait_queue(&runtime->sleep, &wait);
- if (signal_pending(current))
- return result > 0 ? result : -ERESTARTSYS;
- if (runtime->avail == last_avail && !timeout)
- return result > 0 ? result : -EIO;
- spin_lock_irq(&runtime->lock);
- }
- spin_unlock_irq(&runtime->lock);
- }
- return result;
-}
-
-static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
-{
- struct snd_rawmidi_file *rfile;
- struct snd_rawmidi_runtime *runtime;
- unsigned int mask;
-
- rfile = file->private_data;
- if (rfile->input != NULL) {
- runtime = rfile->input->runtime;
- snd_rawmidi_input_trigger(rfile->input, 1);
- poll_wait(file, &runtime->sleep, wait);
- }
- if (rfile->output != NULL) {
- runtime = rfile->output->runtime;
- poll_wait(file, &runtime->sleep, wait);
- }
- mask = 0;
- if (rfile->input != NULL) {
- if (snd_rawmidi_ready(rfile->input))
- mask |= POLLIN | POLLRDNORM;
- }
- if (rfile->output != NULL) {
- if (snd_rawmidi_ready(rfile->output))
- mask |= POLLOUT | POLLWRNORM;
- }
- return mask;
-}
-
-/*
- */
-#ifdef CONFIG_COMPAT
-#include "rawmidi_compat.c"
-#else
-#define snd_rawmidi_ioctl_compat NULL
-#endif
-
-/*
-
- */
-
-static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_rawmidi *rmidi;
- struct snd_rawmidi_substream *substream;
- struct snd_rawmidi_runtime *runtime;
-
- rmidi = entry->private_data;
- snd_iprintf(buffer, "%s\n\n", rmidi->name);
- mutex_lock(&rmidi->open_mutex);
- if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {
- list_for_each_entry(substream,
- &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
- list) {
- snd_iprintf(buffer,
- "Output %d\n"
- " Tx bytes : %lu\n",
- substream->number,
- (unsigned long) substream->bytes);
- if (substream->opened) {
- snd_iprintf(buffer,
- " Owner PID : %d\n",
- pid_vnr(substream->pid));
- runtime = substream->runtime;
- snd_iprintf(buffer,
- " Mode : %s\n"
- " Buffer size : %lu\n"
- " Avail : %lu\n",
- runtime->oss ? "OSS compatible" : "native",
- (unsigned long) runtime->buffer_size,
- (unsigned long) runtime->avail);
- }
- }
- }
- if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT) {
- list_for_each_entry(substream,
- &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams,
- list) {
- snd_iprintf(buffer,
- "Input %d\n"
- " Rx bytes : %lu\n",
- substream->number,
- (unsigned long) substream->bytes);
- if (substream->opened) {
- snd_iprintf(buffer,
- " Owner PID : %d\n",
- pid_vnr(substream->pid));
- runtime = substream->runtime;
- snd_iprintf(buffer,
- " Buffer size : %lu\n"
- " Avail : %lu\n"
- " Overruns : %lu\n",
- (unsigned long) runtime->buffer_size,
- (unsigned long) runtime->avail,
- (unsigned long) runtime->xruns);
- }
- }
- }
- mutex_unlock(&rmidi->open_mutex);
-}
-
-/*
- * Register functions
- */
-
-static const struct file_operations snd_rawmidi_f_ops =
-{
- .owner = THIS_MODULE,
- .read = snd_rawmidi_read,
- .write = snd_rawmidi_write,
- .open = snd_rawmidi_open,
- .release = snd_rawmidi_release,
- .llseek = no_llseek,
- .poll = snd_rawmidi_poll,
- .unlocked_ioctl = snd_rawmidi_ioctl,
- .compat_ioctl = snd_rawmidi_ioctl_compat,
-};
-
-static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
- struct snd_rawmidi_str *stream,
- int direction,
- int count)
-{
- struct snd_rawmidi_substream *substream;
- int idx;
-
- for (idx = 0; idx < count; idx++) {
- substream = kzalloc(sizeof(*substream), GFP_KERNEL);
- if (substream == NULL) {
- snd_printk(KERN_ERR "rawmidi: cannot allocate substream\n");
- return -ENOMEM;
- }
- substream->stream = direction;
- substream->number = idx;
- substream->rmidi = rmidi;
- substream->pstr = stream;
- list_add_tail(&substream->list, &stream->substreams);
- stream->substream_count++;
- }
- return 0;
-}
-
-/**
- * snd_rawmidi_new - create a rawmidi instance
- * @card: the card instance
- * @id: the id string
- * @device: the device index
- * @output_count: the number of output streams
- * @input_count: the number of input streams
- * @rrawmidi: the pointer to store the new rawmidi instance
- *
- * Creates a new rawmidi instance.
- * Use snd_rawmidi_set_ops() to set the operators to the new instance.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_rawmidi_new(struct snd_card *card, char *id, int device,
- int output_count, int input_count,
- struct snd_rawmidi ** rrawmidi)
-{
- struct snd_rawmidi *rmidi;
- int err;
- static struct snd_device_ops ops = {
- .dev_free = snd_rawmidi_dev_free,
- .dev_register = snd_rawmidi_dev_register,
- .dev_disconnect = snd_rawmidi_dev_disconnect,
- };
-
- if (snd_BUG_ON(!card))
- return -ENXIO;
- if (rrawmidi)
- *rrawmidi = NULL;
- rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);
- if (rmidi == NULL) {
- snd_printk(KERN_ERR "rawmidi: cannot allocate\n");
- return -ENOMEM;
- }
- rmidi->card = card;
- rmidi->device = device;
- mutex_init(&rmidi->open_mutex);
- init_waitqueue_head(&rmidi->open_wait);
- INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams);
- INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams);
-
- if (id != NULL)
- strlcpy(rmidi->id, id, sizeof(rmidi->id));
- if ((err = snd_rawmidi_alloc_substreams(rmidi,
- &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],
- SNDRV_RAWMIDI_STREAM_INPUT,
- input_count)) < 0) {
- snd_rawmidi_free(rmidi);
- return err;
- }
- if ((err = snd_rawmidi_alloc_substreams(rmidi,
- &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT],
- SNDRV_RAWMIDI_STREAM_OUTPUT,
- output_count)) < 0) {
- snd_rawmidi_free(rmidi);
- return err;
- }
- if ((err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops)) < 0) {
- snd_rawmidi_free(rmidi);
- return err;
- }
- if (rrawmidi)
- *rrawmidi = rmidi;
- return 0;
-}
-
-static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream)
-{
- struct snd_rawmidi_substream *substream;
-
- while (!list_empty(&stream->substreams)) {
- substream = list_entry(stream->substreams.next, struct snd_rawmidi_substream, list);
- list_del(&substream->list);
- kfree(substream);
- }
-}
-
-static int snd_rawmidi_free(struct snd_rawmidi *rmidi)
-{
- if (!rmidi)
- return 0;
-
- snd_info_free_entry(rmidi->proc_entry);
- rmidi->proc_entry = NULL;
- mutex_lock(&register_mutex);
- if (rmidi->ops && rmidi->ops->dev_unregister)
- rmidi->ops->dev_unregister(rmidi);
- mutex_unlock(&register_mutex);
-
- snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);
- snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
- if (rmidi->private_free)
- rmidi->private_free(rmidi);
- kfree(rmidi);
- return 0;
-}
-
-static int snd_rawmidi_dev_free(struct snd_device *device)
-{
- struct snd_rawmidi *rmidi = device->device_data;
- return snd_rawmidi_free(rmidi);
-}
-
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
-static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device)
-{
- struct snd_rawmidi *rmidi = device->private_data;
- rmidi->seq_dev = NULL;
-}
-#endif
-
-static int snd_rawmidi_dev_register(struct snd_device *device)
-{
- int err;
- struct snd_info_entry *entry;
- char name[16];
- struct snd_rawmidi *rmidi = device->device_data;
-
- if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
- return -ENOMEM;
- mutex_lock(&register_mutex);
- if (snd_rawmidi_search(rmidi->card, rmidi->device)) {
- mutex_unlock(&register_mutex);
- return -EBUSY;
- }
- list_add_tail(&rmidi->list, &snd_rawmidi_devices);
- sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device);
- if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
- rmidi->card, rmidi->device,
- &snd_rawmidi_f_ops, rmidi, name)) < 0) {
- snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device);
- list_del(&rmidi->list);
- mutex_unlock(&register_mutex);
- return err;
- }
- if (rmidi->ops && rmidi->ops->dev_register &&
- (err = rmidi->ops->dev_register(rmidi)) < 0) {
- snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
- list_del(&rmidi->list);
- mutex_unlock(&register_mutex);
- return err;
- }
-#ifdef CONFIG_SND_OSSEMUL
- rmidi->ossreg = 0;
- if ((int)rmidi->device == midi_map[rmidi->card->number]) {
- if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
- rmidi->card, 0, &snd_rawmidi_f_ops,
- rmidi, name) < 0) {
- snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
- } else {
- rmidi->ossreg++;
-#ifdef SNDRV_OSS_INFO_DEV_MIDI
- snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number, rmidi->name);
-#endif
- }
- }
- if ((int)rmidi->device == amidi_map[rmidi->card->number]) {
- if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
- rmidi->card, 1, &snd_rawmidi_f_ops,
- rmidi, name) < 0) {
- snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1);
- } else {
- rmidi->ossreg++;
- }
- }
-#endif /* CONFIG_SND_OSSEMUL */
- mutex_unlock(&register_mutex);
- sprintf(name, "midi%d", rmidi->device);
- entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root);
- if (entry) {
- entry->private_data = rmidi;
- entry->c.text.read = snd_rawmidi_proc_info_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- rmidi->proc_entry = entry;
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
- if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */
- if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) {
- rmidi->seq_dev->private_data = rmidi;
- rmidi->seq_dev->private_free = snd_rawmidi_dev_seq_free;
- sprintf(rmidi->seq_dev->name, "MIDI %d-%d", rmidi->card->number, rmidi->device);
- snd_device_register(rmidi->card, rmidi->seq_dev);
- }
- }
-#endif
- return 0;
-}
-
-static int snd_rawmidi_dev_disconnect(struct snd_device *device)
-{
- struct snd_rawmidi *rmidi = device->device_data;
- int dir;
-
- mutex_lock(&register_mutex);
- mutex_lock(&rmidi->open_mutex);
- wake_up(&rmidi->open_wait);
- list_del_init(&rmidi->list);
- for (dir = 0; dir < 2; dir++) {
- struct snd_rawmidi_substream *s;
- list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
- if (s->runtime)
- wake_up(&s->runtime->sleep);
- }
- }
-
-#ifdef CONFIG_SND_OSSEMUL
- if (rmidi->ossreg) {
- if ((int)rmidi->device == midi_map[rmidi->card->number]) {
- snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 0);
-#ifdef SNDRV_OSS_INFO_DEV_MIDI
- snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number);
-#endif
- }
- if ((int)rmidi->device == amidi_map[rmidi->card->number])
- snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 1);
- rmidi->ossreg = 0;
- }
-#endif /* CONFIG_SND_OSSEMUL */
- snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
- mutex_unlock(&rmidi->open_mutex);
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-/**
- * snd_rawmidi_set_ops - set the rawmidi operators
- * @rmidi: the rawmidi instance
- * @stream: the stream direction, SNDRV_RAWMIDI_STREAM_XXX
- * @ops: the operator table
- *
- * Sets the rawmidi operators for the given stream direction.
- */
-void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
- struct snd_rawmidi_ops *ops)
-{
- struct snd_rawmidi_substream *substream;
-
- list_for_each_entry(substream, &rmidi->streams[stream].substreams, list)
- substream->ops = ops;
-}
-
-/*
- * ENTRY functions
- */
-
-static int __init alsa_rawmidi_init(void)
-{
-
- snd_ctl_register_ioctl(snd_rawmidi_control_ioctl);
- snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl);
-#ifdef CONFIG_SND_OSSEMUL
- { int i;
- /* check device map table */
- for (i = 0; i < SNDRV_CARDS; i++) {
- if (midi_map[i] < 0 || midi_map[i] >= SNDRV_RAWMIDI_DEVICES) {
- snd_printk(KERN_ERR "invalid midi_map[%d] = %d\n", i, midi_map[i]);
- midi_map[i] = 0;
- }
- if (amidi_map[i] < 0 || amidi_map[i] >= SNDRV_RAWMIDI_DEVICES) {
- snd_printk(KERN_ERR "invalid amidi_map[%d] = %d\n", i, amidi_map[i]);
- amidi_map[i] = 1;
- }
- }
- }
-#endif /* CONFIG_SND_OSSEMUL */
- return 0;
-}
-
-static void __exit alsa_rawmidi_exit(void)
-{
- snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl);
- snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl);
-}
-
-module_init(alsa_rawmidi_init)
-module_exit(alsa_rawmidi_exit)
-
-EXPORT_SYMBOL(snd_rawmidi_output_params);
-EXPORT_SYMBOL(snd_rawmidi_input_params);
-EXPORT_SYMBOL(snd_rawmidi_drop_output);
-EXPORT_SYMBOL(snd_rawmidi_drain_output);
-EXPORT_SYMBOL(snd_rawmidi_drain_input);
-EXPORT_SYMBOL(snd_rawmidi_receive);
-EXPORT_SYMBOL(snd_rawmidi_transmit_empty);
-EXPORT_SYMBOL(snd_rawmidi_transmit_peek);
-EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
-EXPORT_SYMBOL(snd_rawmidi_transmit);
-EXPORT_SYMBOL(snd_rawmidi_new);
-EXPORT_SYMBOL(snd_rawmidi_set_ops);
-EXPORT_SYMBOL(snd_rawmidi_info_select);
-EXPORT_SYMBOL(snd_rawmidi_kernel_open);
-EXPORT_SYMBOL(snd_rawmidi_kernel_release);
-EXPORT_SYMBOL(snd_rawmidi_kernel_read);
-EXPORT_SYMBOL(snd_rawmidi_kernel_write);
diff --git a/ANDROID_3.4.5/sound/core/rawmidi_compat.c b/ANDROID_3.4.5/sound/core/rawmidi_compat.c
deleted file mode 100644
index 5268c1f5..00000000
--- a/ANDROID_3.4.5/sound/core/rawmidi_compat.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for raw MIDI API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/* This file included from rawmidi.c */
-
-#include <linux/compat.h>
-
-struct snd_rawmidi_params32 {
- s32 stream;
- u32 buffer_size;
- u32 avail_min;
- unsigned int no_active_sensing; /* avoid bit-field */
- unsigned char reserved[16];
-} __attribute__((packed));
-
-static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
- struct snd_rawmidi_params32 __user *src)
-{
- struct snd_rawmidi_params params;
- unsigned int val;
-
- if (rfile->output == NULL)
- return -EINVAL;
- if (get_user(params.stream, &src->stream) ||
- get_user(params.buffer_size, &src->buffer_size) ||
- get_user(params.avail_min, &src->avail_min) ||
- get_user(val, &src->no_active_sensing))
- return -EFAULT;
- params.no_active_sensing = val;
- switch (params.stream) {
- case SNDRV_RAWMIDI_STREAM_OUTPUT:
- return snd_rawmidi_output_params(rfile->output, &params);
- case SNDRV_RAWMIDI_STREAM_INPUT:
- return snd_rawmidi_input_params(rfile->input, &params);
- }
- return -EINVAL;
-}
-
-struct snd_rawmidi_status32 {
- s32 stream;
- struct compat_timespec tstamp;
- u32 avail;
- u32 xruns;
- unsigned char reserved[16];
-} __attribute__((packed));
-
-static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
- struct snd_rawmidi_status32 __user *src)
-{
- int err;
- struct snd_rawmidi_status status;
-
- if (rfile->output == NULL)
- return -EINVAL;
- if (get_user(status.stream, &src->stream))
- return -EFAULT;
-
- switch (status.stream) {
- case SNDRV_RAWMIDI_STREAM_OUTPUT:
- err = snd_rawmidi_output_status(rfile->output, &status);
- break;
- case SNDRV_RAWMIDI_STREAM_INPUT:
- err = snd_rawmidi_input_status(rfile->input, &status);
- break;
- default:
- return -EINVAL;
- }
- if (err < 0)
- return err;
-
- if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
- put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
- put_user(status.avail, &src->avail) ||
- put_user(status.xruns, &src->xruns))
- return -EFAULT;
-
- return 0;
-}
-
-enum {
- SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
- SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
-};
-
-static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct snd_rawmidi_file *rfile;
- void __user *argp = compat_ptr(arg);
-
- rfile = file->private_data;
- switch (cmd) {
- case SNDRV_RAWMIDI_IOCTL_PVERSION:
- case SNDRV_RAWMIDI_IOCTL_INFO:
- case SNDRV_RAWMIDI_IOCTL_DROP:
- case SNDRV_RAWMIDI_IOCTL_DRAIN:
- return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
- case SNDRV_RAWMIDI_IOCTL_PARAMS32:
- return snd_rawmidi_ioctl_params_compat(rfile, argp);
- case SNDRV_RAWMIDI_IOCTL_STATUS32:
- return snd_rawmidi_ioctl_status_compat(rfile, argp);
- }
- return -ENOIOCTLCMD;
-}
diff --git a/ANDROID_3.4.5/sound/core/rtctimer.c b/ANDROID_3.4.5/sound/core/rtctimer.c
deleted file mode 100644
index e85e72ba..00000000
--- a/ANDROID_3.4.5/sound/core/rtctimer.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * RTC based high-frequency timer
- *
- * Copyright (C) 2000 Takashi Iwai
- * based on rtctimer.c by Steve Ratcliffe
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/log2.h>
-#include <sound/core.h>
-#include <sound/timer.h>
-
-#if defined(CONFIG_RTC) || defined(CONFIG_RTC_MODULE)
-
-#include <linux/mc146818rtc.h>
-
-#define RTC_FREQ 1024 /* default frequency */
-#define NANO_SEC 1000000000L /* 10^9 in sec */
-
-/*
- * prototypes
- */
-static int rtctimer_open(struct snd_timer *t);
-static int rtctimer_close(struct snd_timer *t);
-static int rtctimer_start(struct snd_timer *t);
-static int rtctimer_stop(struct snd_timer *t);
-
-
-/*
- * The hardware dependent description for this timer.
- */
-static struct snd_timer_hardware rtc_hw = {
- .flags = SNDRV_TIMER_HW_AUTO |
- SNDRV_TIMER_HW_FIRST |
- SNDRV_TIMER_HW_TASKLET,
- .ticks = 100000000L, /* FIXME: XXX */
- .open = rtctimer_open,
- .close = rtctimer_close,
- .start = rtctimer_start,
- .stop = rtctimer_stop,
-};
-
-static int rtctimer_freq = RTC_FREQ; /* frequency */
-static struct snd_timer *rtctimer;
-static struct tasklet_struct rtc_tasklet;
-static rtc_task_t rtc_task;
-
-
-static int
-rtctimer_open(struct snd_timer *t)
-{
- int err;
-
- err = rtc_register(&rtc_task);
- if (err < 0)
- return err;
- t->private_data = &rtc_task;
- return 0;
-}
-
-static int
-rtctimer_close(struct snd_timer *t)
-{
- rtc_task_t *rtc = t->private_data;
- if (rtc) {
- rtc_unregister(rtc);
- tasklet_kill(&rtc_tasklet);
- t->private_data = NULL;
- }
- return 0;
-}
-
-static int
-rtctimer_start(struct snd_timer *timer)
-{
- rtc_task_t *rtc = timer->private_data;
- if (snd_BUG_ON(!rtc))
- return -EINVAL;
- rtc_control(rtc, RTC_IRQP_SET, rtctimer_freq);
- rtc_control(rtc, RTC_PIE_ON, 0);
- return 0;
-}
-
-static int
-rtctimer_stop(struct snd_timer *timer)
-{
- rtc_task_t *rtc = timer->private_data;
- if (snd_BUG_ON(!rtc))
- return -EINVAL;
- rtc_control(rtc, RTC_PIE_OFF, 0);
- return 0;
-}
-
-static void rtctimer_tasklet(unsigned long data)
-{
- snd_timer_interrupt((struct snd_timer *)data, 1);
-}
-
-/*
- * interrupt
- */
-static void rtctimer_interrupt(void *private_data)
-{
- tasklet_schedule(private_data);
-}
-
-
-/*
- * ENTRY functions
- */
-static int __init rtctimer_init(void)
-{
- int err;
- struct snd_timer *timer;
-
- if (rtctimer_freq < 2 || rtctimer_freq > 8192 ||
- !is_power_of_2(rtctimer_freq)) {
- snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n",
- rtctimer_freq);
- return -EINVAL;
- }
-
- /* Create a new timer and set up the fields */
- err = snd_timer_global_new("rtc", SNDRV_TIMER_GLOBAL_RTC, &timer);
- if (err < 0)
- return err;
-
- timer->module = THIS_MODULE;
- strcpy(timer->name, "RTC timer");
- timer->hw = rtc_hw;
- timer->hw.resolution = NANO_SEC / rtctimer_freq;
-
- tasklet_init(&rtc_tasklet, rtctimer_tasklet, (unsigned long)timer);
-
- /* set up RTC callback */
- rtc_task.func = rtctimer_interrupt;
- rtc_task.private_data = &rtc_tasklet;
-
- err = snd_timer_global_register(timer);
- if (err < 0) {
- snd_timer_global_free(timer);
- return err;
- }
- rtctimer = timer; /* remember this */
-
- return 0;
-}
-
-static void __exit rtctimer_exit(void)
-{
- if (rtctimer) {
- snd_timer_global_free(rtctimer);
- rtctimer = NULL;
- }
-}
-
-
-/*
- * exported stuff
- */
-module_init(rtctimer_init)
-module_exit(rtctimer_exit)
-
-module_param(rtctimer_freq, int, 0444);
-MODULE_PARM_DESC(rtctimer_freq, "timer frequency in Hz");
-
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_RTC));
-
-#endif /* CONFIG_RTC || CONFIG_RTC_MODULE */
diff --git a/ANDROID_3.4.5/sound/core/seq/Kconfig b/ANDROID_3.4.5/sound/core/seq/Kconfig
deleted file mode 100644
index b851fd89..00000000
--- a/ANDROID_3.4.5/sound/core/seq/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-# define SND_XXX_SEQ to min(SND_SEQUENCER,SND_XXX)
-
-config SND_RAWMIDI_SEQ
- def_tristate SND_SEQUENCER && SND_RAWMIDI
-
-config SND_OPL3_LIB_SEQ
- def_tristate SND_SEQUENCER && SND_OPL3_LIB
-
-config SND_OPL4_LIB_SEQ
- def_tristate SND_SEQUENCER && SND_OPL4_LIB
-
-config SND_SBAWE_SEQ
- def_tristate SND_SEQUENCER && SND_SBAWE
-
-config SND_EMU10K1_SEQ
- def_tristate SND_SEQUENCER && SND_EMU10K1
diff --git a/ANDROID_3.4.5/sound/core/seq/Makefile b/ANDROID_3.4.5/sound/core/seq/Makefile
deleted file mode 100644
index 941f64a8..00000000
--- a/ANDROID_3.4.5/sound/core/seq/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Makefile for ALSA
-# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
-#
-
-snd-seq-device-objs := seq_device.o
-snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
- seq_fifo.o seq_prioq.o seq_timer.o \
- seq_system.o seq_ports.o seq_info.o
-snd-seq-midi-objs := seq_midi.o
-snd-seq-midi-emul-objs := seq_midi_emul.o
-snd-seq-midi-event-objs := seq_midi_event.o
-snd-seq-dummy-objs := seq_dummy.o
-snd-seq-virmidi-objs := seq_virmidi.o
-
-obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o
-ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
- obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
- obj-$(CONFIG_SND_SEQUENCER) += oss/
-endif
-obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
-
-# Toplevel Module Dependency
-obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
-obj-$(CONFIG_SND_RAWMIDI_SEQ) += snd-seq-midi.o snd-seq-midi-event.o
-obj-$(CONFIG_SND_OPL3_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o
-obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o
-obj-$(CONFIG_SND_SBAWE_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o
-obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/Makefile b/ANDROID_3.4.5/sound/core/seq/oss/Makefile
deleted file mode 100644
index b38406b8..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Makefile for ALSA
-# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
-#
-
-snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \
- seq_oss_event.o seq_oss_rw.o seq_oss_synth.o \
- seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.o
-
-obj-$(CONFIG_SND_SEQUENCER) += snd-seq-oss.o
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss.c
deleted file mode 100644
index 8d4d5e85..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * registration of device and proc
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <sound/initval.h>
-#include "seq_oss_device.h"
-#include "seq_oss_synth.h"
-
-/*
- * module option
- */
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("OSS-compatible sequencer module");
-MODULE_LICENSE("GPL");
-/* Takashi says this is really only for sound-service-0-, but this is OK. */
-MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_SEQUENCER);
-MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MUSIC);
-
-#ifdef SNDRV_SEQ_OSS_DEBUG
-module_param(seq_oss_debug, int, 0644);
-MODULE_PARM_DESC(seq_oss_debug, "debug option");
-int seq_oss_debug = 0;
-#endif
-
-
-/*
- * prototypes
- */
-static int register_device(void);
-static void unregister_device(void);
-#ifdef CONFIG_PROC_FS
-static int register_proc(void);
-static void unregister_proc(void);
-#else
-static inline int register_proc(void) { return 0; }
-static inline void unregister_proc(void) {}
-#endif
-
-static int odev_open(struct inode *inode, struct file *file);
-static int odev_release(struct inode *inode, struct file *file);
-static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset);
-static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset);
-static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-static unsigned int odev_poll(struct file *file, poll_table * wait);
-
-
-/*
- * module interface
- */
-
-static int __init alsa_seq_oss_init(void)
-{
- int rc;
- static struct snd_seq_dev_ops ops = {
- snd_seq_oss_synth_register,
- snd_seq_oss_synth_unregister,
- };
-
- snd_seq_autoload_lock();
- if ((rc = register_device()) < 0)
- goto error;
- if ((rc = register_proc()) < 0) {
- unregister_device();
- goto error;
- }
- if ((rc = snd_seq_oss_create_client()) < 0) {
- unregister_proc();
- unregister_device();
- goto error;
- }
-
- if ((rc = snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OSS, &ops,
- sizeof(struct snd_seq_oss_reg))) < 0) {
- snd_seq_oss_delete_client();
- unregister_proc();
- unregister_device();
- goto error;
- }
-
- /* success */
- snd_seq_oss_synth_init();
-
- error:
- snd_seq_autoload_unlock();
- return rc;
-}
-
-static void __exit alsa_seq_oss_exit(void)
-{
- snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OSS);
- snd_seq_oss_delete_client();
- unregister_proc();
- unregister_device();
-}
-
-module_init(alsa_seq_oss_init)
-module_exit(alsa_seq_oss_exit)
-
-/*
- * ALSA minor device interface
- */
-
-static DEFINE_MUTEX(register_mutex);
-
-static int
-odev_open(struct inode *inode, struct file *file)
-{
- int level, rc;
-
- if (iminor(inode) == SNDRV_MINOR_OSS_MUSIC)
- level = SNDRV_SEQ_OSS_MODE_MUSIC;
- else
- level = SNDRV_SEQ_OSS_MODE_SYNTH;
-
- mutex_lock(&register_mutex);
- rc = snd_seq_oss_open(file, level);
- mutex_unlock(&register_mutex);
-
- return rc;
-}
-
-static int
-odev_release(struct inode *inode, struct file *file)
-{
- struct seq_oss_devinfo *dp;
-
- if ((dp = file->private_data) == NULL)
- return 0;
-
- snd_seq_oss_drain_write(dp);
-
- mutex_lock(&register_mutex);
- snd_seq_oss_release(dp);
- mutex_unlock(&register_mutex);
-
- return 0;
-}
-
-static ssize_t
-odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
-{
- struct seq_oss_devinfo *dp;
- dp = file->private_data;
- if (snd_BUG_ON(!dp))
- return -ENXIO;
- return snd_seq_oss_read(dp, buf, count);
-}
-
-
-static ssize_t
-odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
-{
- struct seq_oss_devinfo *dp;
- dp = file->private_data;
- if (snd_BUG_ON(!dp))
- return -ENXIO;
- return snd_seq_oss_write(dp, buf, count, file);
-}
-
-static long
-odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct seq_oss_devinfo *dp;
- dp = file->private_data;
- if (snd_BUG_ON(!dp))
- return -ENXIO;
- return snd_seq_oss_ioctl(dp, cmd, arg);
-}
-
-#ifdef CONFIG_COMPAT
-#define odev_ioctl_compat odev_ioctl
-#else
-#define odev_ioctl_compat NULL
-#endif
-
-static unsigned int
-odev_poll(struct file *file, poll_table * wait)
-{
- struct seq_oss_devinfo *dp;
- dp = file->private_data;
- if (snd_BUG_ON(!dp))
- return -ENXIO;
- return snd_seq_oss_poll(dp, file, wait);
-}
-
-/*
- * registration of sequencer minor device
- */
-
-static const struct file_operations seq_oss_f_ops =
-{
- .owner = THIS_MODULE,
- .read = odev_read,
- .write = odev_write,
- .open = odev_open,
- .release = odev_release,
- .poll = odev_poll,
- .unlocked_ioctl = odev_ioctl,
- .compat_ioctl = odev_ioctl_compat,
- .llseek = noop_llseek,
-};
-
-static int __init
-register_device(void)
-{
- int rc;
-
- mutex_lock(&register_mutex);
- if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
- NULL, 0,
- &seq_oss_f_ops, NULL,
- SNDRV_SEQ_OSS_DEVNAME)) < 0) {
- snd_printk(KERN_ERR "can't register device seq\n");
- mutex_unlock(&register_mutex);
- return rc;
- }
- if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
- NULL, 0,
- &seq_oss_f_ops, NULL,
- SNDRV_SEQ_OSS_DEVNAME)) < 0) {
- snd_printk(KERN_ERR "can't register device music\n");
- snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
- mutex_unlock(&register_mutex);
- return rc;
- }
- debug_printk(("device registered\n"));
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-static void
-unregister_device(void)
-{
- mutex_lock(&register_mutex);
- debug_printk(("device unregistered\n"));
- if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0)
- snd_printk(KERN_ERR "error unregister device music\n");
- if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0)
- snd_printk(KERN_ERR "error unregister device seq\n");
- mutex_unlock(&register_mutex);
-}
-
-/*
- * /proc interface
- */
-
-#ifdef CONFIG_PROC_FS
-
-static struct snd_info_entry *info_entry;
-
-static void
-info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf)
-{
- mutex_lock(&register_mutex);
- snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR);
- snd_seq_oss_system_info_read(buf);
- snd_seq_oss_synth_info_read(buf);
- snd_seq_oss_midi_info_read(buf);
- mutex_unlock(&register_mutex);
-}
-
-
-static int __init
-register_proc(void)
-{
- struct snd_info_entry *entry;
-
- entry = snd_info_create_module_entry(THIS_MODULE, SNDRV_SEQ_OSS_PROCNAME, snd_seq_root);
- if (entry == NULL)
- return -ENOMEM;
-
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->private_data = NULL;
- entry->c.text.read = info_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return -ENOMEM;
- }
- info_entry = entry;
- return 0;
-}
-
-static void
-unregister_proc(void)
-{
- snd_info_free_entry(info_entry);
- info_entry = NULL;
-}
-#endif /* CONFIG_PROC_FS */
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_device.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_device.h
deleted file mode 100644
index c0154a95..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_device.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __SEQ_OSS_DEVICE_H
-#define __SEQ_OSS_DEVICE_H
-
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <sound/core.h>
-#include <sound/seq_oss.h>
-#include <sound/rawmidi.h>
-#include <sound/seq_kernel.h>
-#include <sound/info.h>
-
-/* enable debug print */
-#define SNDRV_SEQ_OSS_DEBUG
-
-/* max. applications */
-#define SNDRV_SEQ_OSS_MAX_CLIENTS 16
-#define SNDRV_SEQ_OSS_MAX_SYNTH_DEVS 16
-#define SNDRV_SEQ_OSS_MAX_MIDI_DEVS 32
-
-/* version */
-#define SNDRV_SEQ_OSS_MAJOR_VERSION 0
-#define SNDRV_SEQ_OSS_MINOR_VERSION 1
-#define SNDRV_SEQ_OSS_TINY_VERSION 8
-#define SNDRV_SEQ_OSS_VERSION_STR "0.1.8"
-
-/* device and proc interface name */
-#define SNDRV_SEQ_OSS_DEVNAME "seq_oss"
-#define SNDRV_SEQ_OSS_PROCNAME "oss"
-
-
-/*
- * type definitions
- */
-
-typedef unsigned int reltime_t;
-typedef unsigned int abstime_t;
-
-
-/*
- * synthesizer channel information
- */
-struct seq_oss_chinfo {
- int note, vel;
-};
-
-/*
- * synthesizer information
- */
-struct seq_oss_synthinfo {
- struct snd_seq_oss_arg arg;
- struct seq_oss_chinfo *ch;
- struct seq_oss_synth_sysex *sysex;
- int nr_voices;
- int opened;
- int is_midi;
- int midi_mapped;
-};
-
-
-/*
- * sequencer client information
- */
-
-struct seq_oss_devinfo {
-
- int index; /* application index */
- int cseq; /* sequencer client number */
- int port; /* sequencer port number */
- int queue; /* sequencer queue number */
-
- struct snd_seq_addr addr; /* address of this device */
-
- int seq_mode; /* sequencer mode */
- int file_mode; /* file access */
-
- /* midi device table */
- int max_mididev;
-
- /* synth device table */
- int max_synthdev;
- struct seq_oss_synthinfo synths[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
- int synth_opened;
-
- /* output queue */
- struct seq_oss_writeq *writeq;
-
- /* midi input queue */
- struct seq_oss_readq *readq;
-
- /* timer */
- struct seq_oss_timer *timer;
-};
-
-
-/*
- * function prototypes
- */
-
-/* create/delete OSS sequencer client */
-int snd_seq_oss_create_client(void);
-int snd_seq_oss_delete_client(void);
-
-/* device file interface */
-int snd_seq_oss_open(struct file *file, int level);
-void snd_seq_oss_release(struct seq_oss_devinfo *dp);
-int snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long arg);
-int snd_seq_oss_read(struct seq_oss_devinfo *dev, char __user *buf, int count);
-int snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count, struct file *opt);
-unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait);
-
-void snd_seq_oss_reset(struct seq_oss_devinfo *dp);
-void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp);
-
-/* */
-void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time);
-
-
-/* proc interface */
-void snd_seq_oss_system_info_read(struct snd_info_buffer *buf);
-void snd_seq_oss_midi_info_read(struct snd_info_buffer *buf);
-void snd_seq_oss_synth_info_read(struct snd_info_buffer *buf);
-void snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf);
-
-/* file mode macros */
-#define is_read_mode(mode) ((mode) & SNDRV_SEQ_OSS_FILE_READ)
-#define is_write_mode(mode) ((mode) & SNDRV_SEQ_OSS_FILE_WRITE)
-#define is_nonblock_mode(mode) ((mode) & SNDRV_SEQ_OSS_FILE_NONBLOCK)
-
-/* dispatch event */
-static inline int
-snd_seq_oss_dispatch(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int atomic, int hop)
-{
- return snd_seq_kernel_client_dispatch(dp->cseq, ev, atomic, hop);
-}
-
-/* ioctl */
-static inline int
-snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg)
-{
- return snd_seq_kernel_client_ctl(dp->cseq, type, arg);
-}
-
-/* fill the addresses in header */
-static inline void
-snd_seq_oss_fill_addr(struct seq_oss_devinfo *dp, struct snd_seq_event *ev,
- int dest_client, int dest_port)
-{
- ev->queue = dp->queue;
- ev->source = dp->addr;
- ev->dest.client = dest_client;
- ev->dest.port = dest_port;
-}
-
-
-/* misc. functions for proc interface */
-char *enabled_str(int bool);
-
-
-/* for debug */
-#ifdef SNDRV_SEQ_OSS_DEBUG
-extern int seq_oss_debug;
-#define debug_printk(x) do { if (seq_oss_debug > 0) snd_printd x; } while (0)
-#else
-#define debug_printk(x) /**/
-#endif
-
-#endif /* __SEQ_OSS_DEVICE_H */
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.c
deleted file mode 100644
index 066f5f3e..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "seq_oss_device.h"
-#include "seq_oss_synth.h"
-#include "seq_oss_midi.h"
-#include "seq_oss_event.h"
-#include "seq_oss_timer.h"
-#include <sound/seq_oss_legacy.h>
-#include "seq_oss_readq.h"
-#include "seq_oss_writeq.h"
-
-
-/*
- * prototypes
- */
-static int extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev);
-static int chn_voice_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
-static int chn_common_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
-static int timing_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
-static int local_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
-static int old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev);
-static int note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev);
-static int note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev);
-static int set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev);
-static int set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev);
-static int set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev);
-
-
-/*
- * convert an OSS event to ALSA event
- * return 0 : enqueued
- * non-zero : invalid - ignored
- */
-
-int
-snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
-{
- switch (q->s.code) {
- case SEQ_EXTENDED:
- return extended_event(dp, q, ev);
-
- case EV_CHN_VOICE:
- return chn_voice_event(dp, q, ev);
-
- case EV_CHN_COMMON:
- return chn_common_event(dp, q, ev);
-
- case EV_TIMING:
- return timing_event(dp, q, ev);
-
- case EV_SEQ_LOCAL:
- return local_event(dp, q, ev);
-
- case EV_SYSEX:
- return snd_seq_oss_synth_sysex(dp, q->x.dev, q->x.buf, ev);
-
- case SEQ_MIDIPUTC:
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
- return -EINVAL;
- /* put a midi byte */
- if (! is_write_mode(dp->file_mode))
- break;
- if (snd_seq_oss_midi_open(dp, q->s.dev, SNDRV_SEQ_OSS_FILE_WRITE))
- break;
- if (snd_seq_oss_midi_filemode(dp, q->s.dev) & SNDRV_SEQ_OSS_FILE_WRITE)
- return snd_seq_oss_midi_putc(dp, q->s.dev, q->s.parm1, ev);
- break;
-
- case SEQ_ECHO:
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
- return -EINVAL;
- return set_echo_event(dp, q, ev);
-
- case SEQ_PRIVATE:
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
- return -EINVAL;
- return snd_seq_oss_synth_raw_event(dp, q->c[1], q->c, ev);
-
- default:
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
- return -EINVAL;
- return old_event(dp, q, ev);
- }
- return -EINVAL;
-}
-
-/* old type events: mode1 only */
-static int
-old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
-{
- switch (q->s.code) {
- case SEQ_NOTEOFF:
- return note_off_event(dp, 0, q->n.chn, q->n.note, q->n.vel, ev);
-
- case SEQ_NOTEON:
- return note_on_event(dp, 0, q->n.chn, q->n.note, q->n.vel, ev);
-
- case SEQ_WAIT:
- /* skip */
- break;
-
- case SEQ_PGMCHANGE:
- return set_control_event(dp, 0, SNDRV_SEQ_EVENT_PGMCHANGE,
- q->n.chn, 0, q->n.note, ev);
-
- case SEQ_SYNCTIMER:
- return snd_seq_oss_timer_reset(dp->timer);
- }
-
- return -EINVAL;
-}
-
-/* 8bytes extended event: mode1 only */
-static int
-extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
-{
- int val;
-
- switch (q->e.cmd) {
- case SEQ_NOTEOFF:
- return note_off_event(dp, q->e.dev, q->e.chn, q->e.p1, q->e.p2, ev);
-
- case SEQ_NOTEON:
- return note_on_event(dp, q->e.dev, q->e.chn, q->e.p1, q->e.p2, ev);
-
- case SEQ_PGMCHANGE:
- return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_PGMCHANGE,
- q->e.chn, 0, q->e.p1, ev);
-
- case SEQ_AFTERTOUCH:
- return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_CHANPRESS,
- q->e.chn, 0, q->e.p1, ev);
-
- case SEQ_BALANCE:
- /* convert -128:127 to 0:127 */
- val = (char)q->e.p1;
- val = (val + 128) / 2;
- return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_CONTROLLER,
- q->e.chn, CTL_PAN, val, ev);
-
- case SEQ_CONTROLLER:
- val = ((short)q->e.p3 << 8) | (short)q->e.p2;
- switch (q->e.p1) {
- case CTRL_PITCH_BENDER: /* SEQ1 V2 control */
- /* -0x2000:0x1fff */
- return set_control_event(dp, q->e.dev,
- SNDRV_SEQ_EVENT_PITCHBEND,
- q->e.chn, 0, val, ev);
- case CTRL_PITCH_BENDER_RANGE:
- /* conversion: 100/semitone -> 128/semitone */
- return set_control_event(dp, q->e.dev,
- SNDRV_SEQ_EVENT_REGPARAM,
- q->e.chn, 0, val*128/100, ev);
- default:
- return set_control_event(dp, q->e.dev,
- SNDRV_SEQ_EVENT_CONTROL14,
- q->e.chn, q->e.p1, val, ev);
- }
-
- case SEQ_VOLMODE:
- return snd_seq_oss_synth_raw_event(dp, q->e.dev, q->c, ev);
-
- }
- return -EINVAL;
-}
-
-/* channel voice events: mode1 and 2 */
-static int
-chn_voice_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
-{
- if (q->v.chn >= 32)
- return -EINVAL;
- switch (q->v.cmd) {
- case MIDI_NOTEON:
- return note_on_event(dp, q->v.dev, q->v.chn, q->v.note, q->v.parm, ev);
-
- case MIDI_NOTEOFF:
- return note_off_event(dp, q->v.dev, q->v.chn, q->v.note, q->v.parm, ev);
-
- case MIDI_KEY_PRESSURE:
- return set_note_event(dp, q->v.dev, SNDRV_SEQ_EVENT_KEYPRESS,
- q->v.chn, q->v.note, q->v.parm, ev);
-
- }
- return -EINVAL;
-}
-
-/* channel common events: mode1 and 2 */
-static int
-chn_common_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
-{
- if (q->l.chn >= 32)
- return -EINVAL;
- switch (q->l.cmd) {
- case MIDI_PGM_CHANGE:
- return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_PGMCHANGE,
- q->l.chn, 0, q->l.p1, ev);
-
- case MIDI_CTL_CHANGE:
- return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_CONTROLLER,
- q->l.chn, q->l.p1, q->l.val, ev);
-
- case MIDI_PITCH_BEND:
- /* conversion: 0:0x3fff -> -0x2000:0x1fff */
- return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_PITCHBEND,
- q->l.chn, 0, q->l.val - 8192, ev);
-
- case MIDI_CHN_PRESSURE:
- return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_CHANPRESS,
- q->l.chn, 0, q->l.val, ev);
- }
- return -EINVAL;
-}
-
-/* timer events: mode1 and mode2 */
-static int
-timing_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
-{
- switch (q->t.cmd) {
- case TMR_ECHO:
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
- return set_echo_event(dp, q, ev);
- else {
- union evrec tmp;
- memset(&tmp, 0, sizeof(tmp));
- /* XXX: only for little-endian! */
- tmp.echo = (q->t.time << 8) | SEQ_ECHO;
- return set_echo_event(dp, &tmp, ev);
- }
-
- case TMR_STOP:
- if (dp->seq_mode)
- return snd_seq_oss_timer_stop(dp->timer);
- return 0;
-
- case TMR_CONTINUE:
- if (dp->seq_mode)
- return snd_seq_oss_timer_continue(dp->timer);
- return 0;
-
- case TMR_TEMPO:
- if (dp->seq_mode)
- return snd_seq_oss_timer_tempo(dp->timer, q->t.time);
- return 0;
- }
-
- return -EINVAL;
-}
-
-/* local events: mode1 and 2 */
-static int
-local_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
-{
- return -EINVAL;
-}
-
-/*
- * process note-on event for OSS synth
- * three different modes are available:
- * - SNDRV_SEQ_OSS_PROCESS_EVENTS (for one-voice per channel mode)
- * Accept note 255 as volume change.
- * - SNDRV_SEQ_OSS_PASS_EVENTS
- * Pass all events to lowlevel driver anyway
- * - SNDRV_SEQ_OSS_PROCESS_KEYPRESS (mostly for Emu8000)
- * Use key-pressure if note >= 128
- */
-static int
-note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
-{
- struct seq_oss_synthinfo *info = &dp->synths[dev];
- switch (info->arg.event_passing) {
- case SNDRV_SEQ_OSS_PROCESS_EVENTS:
- if (! info->ch || ch < 0 || ch >= info->nr_voices) {
- /* pass directly */
- return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
- }
-
- if (note == 255 && info->ch[ch].note >= 0) {
- /* volume control */
- int type;
- //if (! vel)
- /* set volume to zero -- note off */
- // type = SNDRV_SEQ_EVENT_NOTEOFF;
- //else
- if (info->ch[ch].vel)
- /* sample already started -- volume change */
- type = SNDRV_SEQ_EVENT_KEYPRESS;
- else
- /* sample not started -- start now */
- type = SNDRV_SEQ_EVENT_NOTEON;
- info->ch[ch].vel = vel;
- return set_note_event(dp, dev, type, ch, info->ch[ch].note, vel, ev);
- } else if (note >= 128)
- return -EINVAL; /* invalid */
-
- if (note != info->ch[ch].note && info->ch[ch].note >= 0)
- /* note changed - note off at beginning */
- set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, info->ch[ch].note, 0, ev);
- /* set current status */
- info->ch[ch].note = note;
- info->ch[ch].vel = vel;
- if (vel) /* non-zero velocity - start the note now */
- return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
- return -EINVAL;
-
- case SNDRV_SEQ_OSS_PASS_EVENTS:
- /* pass the event anyway */
- return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
-
- case SNDRV_SEQ_OSS_PROCESS_KEYPRESS:
- if (note >= 128) /* key pressure: shifted by 128 */
- return set_note_event(dp, dev, SNDRV_SEQ_EVENT_KEYPRESS, ch, note - 128, vel, ev);
- else /* normal note-on event */
- return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
- }
- return -EINVAL;
-}
-
-/*
- * process note-off event for OSS synth
- */
-static int
-note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
-{
- struct seq_oss_synthinfo *info = &dp->synths[dev];
- switch (info->arg.event_passing) {
- case SNDRV_SEQ_OSS_PROCESS_EVENTS:
- if (! info->ch || ch < 0 || ch >= info->nr_voices) {
- /* pass directly */
- return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
- }
-
- if (info->ch[ch].note >= 0) {
- note = info->ch[ch].note;
- info->ch[ch].vel = 0;
- info->ch[ch].note = -1;
- return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, note, vel, ev);
- }
- return -EINVAL; /* invalid */
-
- case SNDRV_SEQ_OSS_PASS_EVENTS:
- case SNDRV_SEQ_OSS_PROCESS_KEYPRESS:
- /* pass the event anyway */
- return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, note, vel, ev);
-
- }
- return -EINVAL;
-}
-
-/*
- * create a note event
- */
-static int
-set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev)
-{
- if (! snd_seq_oss_synth_is_valid(dp, dev))
- return -ENXIO;
-
- ev->type = type;
- snd_seq_oss_synth_addr(dp, dev, ev);
- ev->data.note.channel = ch;
- ev->data.note.note = note;
- ev->data.note.velocity = vel;
-
- return 0;
-}
-
-/*
- * create a control event
- */
-static int
-set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev)
-{
- if (! snd_seq_oss_synth_is_valid(dp, dev))
- return -ENXIO;
-
- ev->type = type;
- snd_seq_oss_synth_addr(dp, dev, ev);
- ev->data.control.channel = ch;
- ev->data.control.param = param;
- ev->data.control.value = val;
-
- return 0;
-}
-
-/*
- * create an echo event
- */
-static int
-set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev)
-{
- ev->type = SNDRV_SEQ_EVENT_ECHO;
- /* echo back to itself */
- snd_seq_oss_fill_addr(dp, ev, dp->addr.client, dp->addr.port);
- memcpy(&ev->data, rec, LONG_EVENT_SIZE);
- return 0;
-}
-
-/*
- * event input callback from ALSA sequencer:
- * the echo event is processed here.
- */
-int
-snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data,
- int atomic, int hop)
-{
- struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
- union evrec *rec;
-
- if (ev->type != SNDRV_SEQ_EVENT_ECHO)
- return snd_seq_oss_midi_input(ev, direct, private_data);
-
- if (ev->source.client != dp->cseq)
- return 0; /* ignored */
-
- rec = (union evrec*)&ev->data;
- if (rec->s.code == SEQ_SYNCTIMER) {
- /* sync echo back */
- snd_seq_oss_writeq_wakeup(dp->writeq, rec->t.time);
-
- } else {
- /* echo back event */
- if (dp->readq == NULL)
- return 0;
- snd_seq_oss_readq_put_event(dp->readq, rec);
- }
- return 0;
-}
-
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.h
deleted file mode 100644
index 9a4d9adb..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * seq_oss_event.h - OSS event queue record
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __SEQ_OSS_EVENT_H
-#define __SEQ_OSS_EVENT_H
-
-#include "seq_oss_device.h"
-
-#define SHORT_EVENT_SIZE 4
-#define LONG_EVENT_SIZE 8
-
-/* short event (4bytes) */
-struct evrec_short {
- unsigned char code;
- unsigned char parm1;
- unsigned char dev;
- unsigned char parm2;
-};
-
-/* short note events (4bytes) */
-struct evrec_note {
- unsigned char code;
- unsigned char chn;
- unsigned char note;
- unsigned char vel;
-};
-
-/* long timer events (8bytes) */
-struct evrec_timer {
- unsigned char code;
- unsigned char cmd;
- unsigned char dummy1, dummy2;
- unsigned int time;
-};
-
-/* long extended events (8bytes) */
-struct evrec_extended {
- unsigned char code;
- unsigned char cmd;
- unsigned char dev;
- unsigned char chn;
- unsigned char p1, p2, p3, p4;
-};
-
-/* long channel events (8bytes) */
-struct evrec_long {
- unsigned char code;
- unsigned char dev;
- unsigned char cmd;
- unsigned char chn;
- unsigned char p1, p2;
- unsigned short val;
-};
-
-/* channel voice events (8bytes) */
-struct evrec_voice {
- unsigned char code;
- unsigned char dev;
- unsigned char cmd;
- unsigned char chn;
- unsigned char note, parm;
- unsigned short dummy;
-};
-
-/* sysex events (8bytes) */
-struct evrec_sysex {
- unsigned char code;
- unsigned char dev;
- unsigned char buf[6];
-};
-
-/* event record */
-union evrec {
- struct evrec_short s;
- struct evrec_note n;
- struct evrec_long l;
- struct evrec_voice v;
- struct evrec_timer t;
- struct evrec_extended e;
- struct evrec_sysex x;
- unsigned int echo;
- unsigned char c[LONG_EVENT_SIZE];
-};
-
-#define ev_is_long(ev) ((ev)->s.code >= 128)
-#define ev_length(ev) ((ev)->s.code >= 128 ? LONG_EVENT_SIZE : SHORT_EVENT_SIZE)
-
-int snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev);
-int snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *q);
-int snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data, int atomic, int hop);
-
-
-#endif /* __SEQ_OSS_EVENT_H */
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_init.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_init.c
deleted file mode 100644
index e3cb46fe..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_init.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * open/close and reset interface
- *
- * Copyright (C) 1998-1999 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "seq_oss_device.h"
-#include "seq_oss_synth.h"
-#include "seq_oss_midi.h"
-#include "seq_oss_writeq.h"
-#include "seq_oss_readq.h"
-#include "seq_oss_timer.h"
-#include "seq_oss_event.h"
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-
-/*
- * common variables
- */
-static int maxqlen = SNDRV_SEQ_OSS_MAX_QLEN;
-module_param(maxqlen, int, 0444);
-MODULE_PARM_DESC(maxqlen, "maximum queue length");
-
-static int system_client = -1; /* ALSA sequencer client number */
-static int system_port = -1;
-
-static int num_clients;
-static struct seq_oss_devinfo *client_table[SNDRV_SEQ_OSS_MAX_CLIENTS];
-
-
-/*
- * prototypes
- */
-static int receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop);
-static int translate_mode(struct file *file);
-static int create_port(struct seq_oss_devinfo *dp);
-static int delete_port(struct seq_oss_devinfo *dp);
-static int alloc_seq_queue(struct seq_oss_devinfo *dp);
-static int delete_seq_queue(int queue);
-static void free_devinfo(void *private);
-
-#define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec)
-
-
-/*
- * create sequencer client for OSS sequencer
- */
-int __init
-snd_seq_oss_create_client(void)
-{
- int rc;
- struct snd_seq_port_info *port;
- struct snd_seq_port_callback port_callback;
-
- port = kmalloc(sizeof(*port), GFP_KERNEL);
- if (!port) {
- rc = -ENOMEM;
- goto __error;
- }
-
- /* create ALSA client */
- rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS,
- "OSS sequencer");
- if (rc < 0)
- goto __error;
-
- system_client = rc;
- debug_printk(("new client = %d\n", rc));
-
- /* look up midi devices */
- snd_seq_oss_midi_lookup_ports(system_client);
-
- /* create annoucement receiver port */
- memset(port, 0, sizeof(*port));
- strcpy(port->name, "Receiver");
- port->addr.client = system_client;
- port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */
- port->type = 0;
-
- memset(&port_callback, 0, sizeof(port_callback));
- /* don't set port_callback.owner here. otherwise the module counter
- * is incremented and we can no longer release the module..
- */
- port_callback.event_input = receive_announce;
- port->kernel = &port_callback;
-
- call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port);
- if ((system_port = port->addr.port) >= 0) {
- struct snd_seq_port_subscribe subs;
-
- memset(&subs, 0, sizeof(subs));
- subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
- subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
- subs.dest.client = system_client;
- subs.dest.port = system_port;
- call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs);
- }
- rc = 0;
-
- __error:
- kfree(port);
- return rc;
-}
-
-
-/*
- * receive annoucement from system port, and check the midi device
- */
-static int
-receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop)
-{
- struct snd_seq_port_info pinfo;
-
- if (atomic)
- return 0; /* it must not happen */
-
- switch (ev->type) {
- case SNDRV_SEQ_EVENT_PORT_START:
- case SNDRV_SEQ_EVENT_PORT_CHANGE:
- if (ev->data.addr.client == system_client)
- break; /* ignore myself */
- memset(&pinfo, 0, sizeof(pinfo));
- pinfo.addr = ev->data.addr;
- if (call_ctl(SNDRV_SEQ_IOCTL_GET_PORT_INFO, &pinfo) >= 0)
- snd_seq_oss_midi_check_new_port(&pinfo);
- break;
-
- case SNDRV_SEQ_EVENT_PORT_EXIT:
- if (ev->data.addr.client == system_client)
- break; /* ignore myself */
- snd_seq_oss_midi_check_exit_port(ev->data.addr.client,
- ev->data.addr.port);
- break;
- }
- return 0;
-}
-
-
-/*
- * delete OSS sequencer client
- */
-int
-snd_seq_oss_delete_client(void)
-{
- if (system_client >= 0)
- snd_seq_delete_kernel_client(system_client);
-
- snd_seq_oss_midi_clear_all();
-
- return 0;
-}
-
-
-/*
- * open sequencer device
- */
-int
-snd_seq_oss_open(struct file *file, int level)
-{
- int i, rc;
- struct seq_oss_devinfo *dp;
-
- dp = kzalloc(sizeof(*dp), GFP_KERNEL);
- if (!dp) {
- snd_printk(KERN_ERR "can't malloc device info\n");
- return -ENOMEM;
- }
- debug_printk(("oss_open: dp = %p\n", dp));
-
- dp->cseq = system_client;
- dp->port = -1;
- dp->queue = -1;
-
- for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) {
- if (client_table[i] == NULL)
- break;
- }
-
- dp->index = i;
- if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
- snd_printk(KERN_ERR "too many applications\n");
- rc = -ENOMEM;
- goto _error;
- }
-
- /* look up synth and midi devices */
- snd_seq_oss_synth_setup(dp);
- snd_seq_oss_midi_setup(dp);
-
- if (dp->synth_opened == 0 && dp->max_mididev == 0) {
- /* snd_printk(KERN_ERR "no device found\n"); */
- rc = -ENODEV;
- goto _error;
- }
-
- /* create port */
- debug_printk(("create new port\n"));
- rc = create_port(dp);
- if (rc < 0) {
- snd_printk(KERN_ERR "can't create port\n");
- goto _error;
- }
-
- /* allocate queue */
- debug_printk(("allocate queue\n"));
- rc = alloc_seq_queue(dp);
- if (rc < 0)
- goto _error;
-
- /* set address */
- dp->addr.client = dp->cseq;
- dp->addr.port = dp->port;
- /*dp->addr.queue = dp->queue;*/
- /*dp->addr.channel = 0;*/
-
- dp->seq_mode = level;
-
- /* set up file mode */
- dp->file_mode = translate_mode(file);
-
- /* initialize read queue */
- debug_printk(("initialize read queue\n"));
- if (is_read_mode(dp->file_mode)) {
- dp->readq = snd_seq_oss_readq_new(dp, maxqlen);
- if (!dp->readq) {
- rc = -ENOMEM;
- goto _error;
- }
- }
-
- /* initialize write queue */
- debug_printk(("initialize write queue\n"));
- if (is_write_mode(dp->file_mode)) {
- dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen);
- if (!dp->writeq) {
- rc = -ENOMEM;
- goto _error;
- }
- }
-
- /* initialize timer */
- debug_printk(("initialize timer\n"));
- dp->timer = snd_seq_oss_timer_new(dp);
- if (!dp->timer) {
- snd_printk(KERN_ERR "can't alloc timer\n");
- rc = -ENOMEM;
- goto _error;
- }
- debug_printk(("timer initialized\n"));
-
- /* set private data pointer */
- file->private_data = dp;
-
- /* set up for mode2 */
- if (level == SNDRV_SEQ_OSS_MODE_MUSIC)
- snd_seq_oss_synth_setup_midi(dp);
- else if (is_read_mode(dp->file_mode))
- snd_seq_oss_midi_open_all(dp, SNDRV_SEQ_OSS_FILE_READ);
-
- client_table[dp->index] = dp;
- num_clients++;
-
- debug_printk(("open done\n"));
- return 0;
-
- _error:
- snd_seq_oss_synth_cleanup(dp);
- snd_seq_oss_midi_cleanup(dp);
- delete_seq_queue(dp->queue);
- delete_port(dp);
-
- return rc;
-}
-
-/*
- * translate file flags to private mode
- */
-static int
-translate_mode(struct file *file)
-{
- int file_mode = 0;
- if ((file->f_flags & O_ACCMODE) != O_RDONLY)
- file_mode |= SNDRV_SEQ_OSS_FILE_WRITE;
- if ((file->f_flags & O_ACCMODE) != O_WRONLY)
- file_mode |= SNDRV_SEQ_OSS_FILE_READ;
- if (file->f_flags & O_NONBLOCK)
- file_mode |= SNDRV_SEQ_OSS_FILE_NONBLOCK;
- return file_mode;
-}
-
-
-/*
- * create sequencer port
- */
-static int
-create_port(struct seq_oss_devinfo *dp)
-{
- int rc;
- struct snd_seq_port_info port;
- struct snd_seq_port_callback callback;
-
- memset(&port, 0, sizeof(port));
- port.addr.client = dp->cseq;
- sprintf(port.name, "Sequencer-%d", dp->index);
- port.capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_WRITE; /* no subscription */
- port.type = SNDRV_SEQ_PORT_TYPE_SPECIFIC;
- port.midi_channels = 128;
- port.synth_voices = 128;
-
- memset(&callback, 0, sizeof(callback));
- callback.owner = THIS_MODULE;
- callback.private_data = dp;
- callback.event_input = snd_seq_oss_event_input;
- callback.private_free = free_devinfo;
- port.kernel = &callback;
-
- rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
- if (rc < 0)
- return rc;
-
- dp->port = port.addr.port;
- debug_printk(("new port = %d\n", port.addr.port));
-
- return 0;
-}
-
-/*
- * delete ALSA port
- */
-static int
-delete_port(struct seq_oss_devinfo *dp)
-{
- if (dp->port < 0) {
- kfree(dp);
- return 0;
- }
-
- debug_printk(("delete_port %i\n", dp->port));
- return snd_seq_event_port_detach(dp->cseq, dp->port);
-}
-
-/*
- * allocate a queue
- */
-static int
-alloc_seq_queue(struct seq_oss_devinfo *dp)
-{
- struct snd_seq_queue_info qinfo;
- int rc;
-
- memset(&qinfo, 0, sizeof(qinfo));
- qinfo.owner = system_client;
- qinfo.locked = 1;
- strcpy(qinfo.name, "OSS Sequencer Emulation");
- if ((rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo)) < 0)
- return rc;
- dp->queue = qinfo.queue;
- return 0;
-}
-
-/*
- * release queue
- */
-static int
-delete_seq_queue(int queue)
-{
- struct snd_seq_queue_info qinfo;
- int rc;
-
- if (queue < 0)
- return 0;
- memset(&qinfo, 0, sizeof(qinfo));
- qinfo.queue = queue;
- rc = call_ctl(SNDRV_SEQ_IOCTL_DELETE_QUEUE, &qinfo);
- if (rc < 0)
- printk(KERN_ERR "seq-oss: unable to delete queue %d (%d)\n", queue, rc);
- return rc;
-}
-
-
-/*
- * free device informations - private_free callback of port
- */
-static void
-free_devinfo(void *private)
-{
- struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private;
-
- if (dp->timer)
- snd_seq_oss_timer_delete(dp->timer);
-
- if (dp->writeq)
- snd_seq_oss_writeq_delete(dp->writeq);
-
- if (dp->readq)
- snd_seq_oss_readq_delete(dp->readq);
-
- kfree(dp);
-}
-
-
-/*
- * close sequencer device
- */
-void
-snd_seq_oss_release(struct seq_oss_devinfo *dp)
-{
- int queue;
-
- client_table[dp->index] = NULL;
- num_clients--;
-
- debug_printk(("resetting..\n"));
- snd_seq_oss_reset(dp);
-
- debug_printk(("cleaning up..\n"));
- snd_seq_oss_synth_cleanup(dp);
- snd_seq_oss_midi_cleanup(dp);
-
- /* clear slot */
- debug_printk(("releasing resource..\n"));
- queue = dp->queue;
- if (dp->port >= 0)
- delete_port(dp);
- delete_seq_queue(queue);
-
- debug_printk(("release done\n"));
-}
-
-
-/*
- * Wait until the queue is empty (if we don't have nonblock)
- */
-void
-snd_seq_oss_drain_write(struct seq_oss_devinfo *dp)
-{
- if (! dp->timer->running)
- return;
- if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) &&
- dp->writeq) {
- debug_printk(("syncing..\n"));
- while (snd_seq_oss_writeq_sync(dp->writeq))
- ;
- }
-}
-
-
-/*
- * reset sequencer devices
- */
-void
-snd_seq_oss_reset(struct seq_oss_devinfo *dp)
-{
- int i;
-
- /* reset all synth devices */
- for (i = 0; i < dp->max_synthdev; i++)
- snd_seq_oss_synth_reset(dp, i);
-
- /* reset all midi devices */
- if (dp->seq_mode != SNDRV_SEQ_OSS_MODE_MUSIC) {
- for (i = 0; i < dp->max_mididev; i++)
- snd_seq_oss_midi_reset(dp, i);
- }
-
- /* remove queues */
- if (dp->readq)
- snd_seq_oss_readq_clear(dp->readq);
- if (dp->writeq)
- snd_seq_oss_writeq_clear(dp->writeq);
-
- /* reset timer */
- snd_seq_oss_timer_stop(dp->timer);
-}
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * misc. functions for proc interface
- */
-char *
-enabled_str(int bool)
-{
- return bool ? "enabled" : "disabled";
-}
-
-static char *
-filemode_str(int val)
-{
- static char *str[] = {
- "none", "read", "write", "read/write",
- };
- return str[val & SNDRV_SEQ_OSS_FILE_ACMODE];
-}
-
-
-/*
- * proc interface
- */
-void
-snd_seq_oss_system_info_read(struct snd_info_buffer *buf)
-{
- int i;
- struct seq_oss_devinfo *dp;
-
- snd_iprintf(buf, "ALSA client number %d\n", system_client);
- snd_iprintf(buf, "ALSA receiver port %d\n", system_port);
-
- snd_iprintf(buf, "\nNumber of applications: %d\n", num_clients);
- for (i = 0; i < num_clients; i++) {
- snd_iprintf(buf, "\nApplication %d: ", i);
- if ((dp = client_table[i]) == NULL) {
- snd_iprintf(buf, "*empty*\n");
- continue;
- }
- snd_iprintf(buf, "port %d : queue %d\n", dp->port, dp->queue);
- snd_iprintf(buf, " sequencer mode = %s : file open mode = %s\n",
- (dp->seq_mode ? "music" : "synth"),
- filemode_str(dp->file_mode));
- if (dp->seq_mode)
- snd_iprintf(buf, " timer tempo = %d, timebase = %d\n",
- dp->timer->oss_tempo, dp->timer->oss_timebase);
- snd_iprintf(buf, " max queue length %d\n", maxqlen);
- if (is_read_mode(dp->file_mode) && dp->readq)
- snd_seq_oss_readq_info_read(dp->readq, buf);
- }
-}
-#endif /* CONFIG_PROC_FS */
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_ioctl.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_ioctl.c
deleted file mode 100644
index 5ac701c9..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_ioctl.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * OSS compatible i/o control
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "seq_oss_device.h"
-#include "seq_oss_readq.h"
-#include "seq_oss_writeq.h"
-#include "seq_oss_timer.h"
-#include "seq_oss_synth.h"
-#include "seq_oss_midi.h"
-#include "seq_oss_event.h"
-
-static int snd_seq_oss_synth_info_user(struct seq_oss_devinfo *dp, void __user *arg)
-{
- struct synth_info info;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
- if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0)
- return -EINVAL;
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_seq_oss_midi_info_user(struct seq_oss_devinfo *dp, void __user *arg)
-{
- struct midi_info info;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
- if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)
- return -EINVAL;
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)
-{
- unsigned char ev[8];
- struct snd_seq_event tmpev;
-
- if (copy_from_user(ev, arg, 8))
- return -EFAULT;
- memset(&tmpev, 0, sizeof(tmpev));
- snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
- tmpev.time.tick = 0;
- if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) {
- snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
- }
- return 0;
-}
-
-int
-snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg)
-{
- int dev, val;
- void __user *arg = (void __user *)carg;
- int __user *p = arg;
-
- switch (cmd) {
- case SNDCTL_TMR_TIMEBASE:
- case SNDCTL_TMR_TEMPO:
- case SNDCTL_TMR_START:
- case SNDCTL_TMR_STOP:
- case SNDCTL_TMR_CONTINUE:
- case SNDCTL_TMR_METRONOME:
- case SNDCTL_TMR_SOURCE:
- case SNDCTL_TMR_SELECT:
- case SNDCTL_SEQ_CTRLRATE:
- return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg);
-
- case SNDCTL_SEQ_PANIC:
- debug_printk(("panic\n"));
- snd_seq_oss_reset(dp);
- return -EINVAL;
-
- case SNDCTL_SEQ_SYNC:
- debug_printk(("sync\n"));
- if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
- return 0;
- while (snd_seq_oss_writeq_sync(dp->writeq))
- ;
- if (signal_pending(current))
- return -ERESTARTSYS;
- return 0;
-
- case SNDCTL_SEQ_RESET:
- debug_printk(("reset\n"));
- snd_seq_oss_reset(dp);
- return 0;
-
- case SNDCTL_SEQ_TESTMIDI:
- debug_printk(("test midi\n"));
- if (get_user(dev, p))
- return -EFAULT;
- return snd_seq_oss_midi_open(dp, dev, dp->file_mode);
-
- case SNDCTL_SEQ_GETINCOUNT:
- debug_printk(("get in count\n"));
- if (dp->readq == NULL || ! is_read_mode(dp->file_mode))
- return 0;
- return put_user(dp->readq->qlen, p) ? -EFAULT : 0;
-
- case SNDCTL_SEQ_GETOUTCOUNT:
- debug_printk(("get out count\n"));
- if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
- return 0;
- return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0;
-
- case SNDCTL_SEQ_GETTIME:
- debug_printk(("get time\n"));
- return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0;
-
- case SNDCTL_SEQ_RESETSAMPLES:
- debug_printk(("reset samples\n"));
- if (get_user(dev, p))
- return -EFAULT;
- return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
-
- case SNDCTL_SEQ_NRSYNTHS:
- debug_printk(("nr synths\n"));
- return put_user(dp->max_synthdev, p) ? -EFAULT : 0;
-
- case SNDCTL_SEQ_NRMIDIS:
- debug_printk(("nr midis\n"));
- return put_user(dp->max_mididev, p) ? -EFAULT : 0;
-
- case SNDCTL_SYNTH_MEMAVL:
- debug_printk(("mem avail\n"));
- if (get_user(dev, p))
- return -EFAULT;
- val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
- return put_user(val, p) ? -EFAULT : 0;
-
- case SNDCTL_FM_4OP_ENABLE:
- debug_printk(("4op\n"));
- if (get_user(dev, p))
- return -EFAULT;
- snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
- return 0;
-
- case SNDCTL_SYNTH_INFO:
- case SNDCTL_SYNTH_ID:
- debug_printk(("synth info\n"));
- return snd_seq_oss_synth_info_user(dp, arg);
-
- case SNDCTL_SEQ_OUTOFBAND:
- debug_printk(("out of band\n"));
- return snd_seq_oss_oob_user(dp, arg);
-
- case SNDCTL_MIDI_INFO:
- debug_printk(("midi info\n"));
- return snd_seq_oss_midi_info_user(dp, arg);
-
- case SNDCTL_SEQ_THRESHOLD:
- debug_printk(("threshold\n"));
- if (! is_write_mode(dp->file_mode))
- return 0;
- if (get_user(val, p))
- return -EFAULT;
- if (val < 1)
- val = 1;
- if (val >= dp->writeq->maxlen)
- val = dp->writeq->maxlen - 1;
- snd_seq_oss_writeq_set_output(dp->writeq, val);
- return 0;
-
- case SNDCTL_MIDI_PRETIME:
- debug_printk(("pretime\n"));
- if (dp->readq == NULL || !is_read_mode(dp->file_mode))
- return 0;
- if (get_user(val, p))
- return -EFAULT;
- if (val <= 0)
- val = -1;
- else
- val = (HZ * val) / 10;
- dp->readq->pre_event_timeout = val;
- return put_user(val, p) ? -EFAULT : 0;
-
- default:
- debug_printk(("others\n"));
- if (! is_write_mode(dp->file_mode))
- return -EIO;
- return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg);
- }
- return 0;
-}
-
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.c
deleted file mode 100644
index 677dc845..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * MIDI device handlers
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <sound/asoundef.h>
-#include "seq_oss_midi.h"
-#include "seq_oss_readq.h"
-#include "seq_oss_timer.h"
-#include "seq_oss_event.h"
-#include <sound/seq_midi_event.h>
-#include "../seq_lock.h"
-#include <linux/init.h>
-#include <linux/slab.h>
-
-
-/*
- * constants
- */
-#define SNDRV_SEQ_OSS_MAX_MIDI_NAME 30
-
-/*
- * definition of midi device record
- */
-struct seq_oss_midi {
- int seq_device; /* device number */
- int client; /* sequencer client number */
- int port; /* sequencer port number */
- unsigned int flags; /* port capability */
- int opened; /* flag for opening */
- unsigned char name[SNDRV_SEQ_OSS_MAX_MIDI_NAME];
- struct snd_midi_event *coder; /* MIDI event coder */
- struct seq_oss_devinfo *devinfo; /* assigned OSSseq device */
- snd_use_lock_t use_lock;
-};
-
-
-/*
- * midi device table
- */
-static int max_midi_devs;
-static struct seq_oss_midi *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
-
-static DEFINE_SPINLOCK(register_lock);
-
-/*
- * prototypes
- */
-static struct seq_oss_midi *get_mdev(int dev);
-static struct seq_oss_midi *get_mididev(struct seq_oss_devinfo *dp, int dev);
-static int send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev);
-static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev);
-
-/*
- * look up the existing ports
- * this looks a very exhausting job.
- */
-int __init
-snd_seq_oss_midi_lookup_ports(int client)
-{
- struct snd_seq_client_info *clinfo;
- struct snd_seq_port_info *pinfo;
-
- clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
- pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
- if (! clinfo || ! pinfo) {
- kfree(clinfo);
- kfree(pinfo);
- return -ENOMEM;
- }
- clinfo->client = -1;
- while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) {
- if (clinfo->client == client)
- continue; /* ignore myself */
- pinfo->addr.client = clinfo->client;
- pinfo->addr.port = -1;
- while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, pinfo) == 0)
- snd_seq_oss_midi_check_new_port(pinfo);
- }
- kfree(clinfo);
- kfree(pinfo);
- return 0;
-}
-
-
-/*
- */
-static struct seq_oss_midi *
-get_mdev(int dev)
-{
- struct seq_oss_midi *mdev;
- unsigned long flags;
-
- spin_lock_irqsave(&register_lock, flags);
- mdev = midi_devs[dev];
- if (mdev)
- snd_use_lock_use(&mdev->use_lock);
- spin_unlock_irqrestore(&register_lock, flags);
- return mdev;
-}
-
-/*
- * look for the identical slot
- */
-static struct seq_oss_midi *
-find_slot(int client, int port)
-{
- int i;
- struct seq_oss_midi *mdev;
- unsigned long flags;
-
- spin_lock_irqsave(&register_lock, flags);
- for (i = 0; i < max_midi_devs; i++) {
- mdev = midi_devs[i];
- if (mdev && mdev->client == client && mdev->port == port) {
- /* found! */
- snd_use_lock_use(&mdev->use_lock);
- spin_unlock_irqrestore(&register_lock, flags);
- return mdev;
- }
- }
- spin_unlock_irqrestore(&register_lock, flags);
- return NULL;
-}
-
-
-#define PERM_WRITE (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE)
-#define PERM_READ (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ)
-/*
- * register a new port if it doesn't exist yet
- */
-int
-snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
-{
- int i;
- struct seq_oss_midi *mdev;
- unsigned long flags;
-
- debug_printk(("check for MIDI client %d port %d\n", pinfo->addr.client, pinfo->addr.port));
- /* the port must include generic midi */
- if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC))
- return 0;
- /* either read or write subscribable */
- if ((pinfo->capability & PERM_WRITE) != PERM_WRITE &&
- (pinfo->capability & PERM_READ) != PERM_READ)
- return 0;
-
- /*
- * look for the identical slot
- */
- if ((mdev = find_slot(pinfo->addr.client, pinfo->addr.port)) != NULL) {
- /* already exists */
- snd_use_lock_free(&mdev->use_lock);
- return 0;
- }
-
- /*
- * allocate midi info record
- */
- if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
- snd_printk(KERN_ERR "can't malloc midi info\n");
- return -ENOMEM;
- }
-
- /* copy the port information */
- mdev->client = pinfo->addr.client;
- mdev->port = pinfo->addr.port;
- mdev->flags = pinfo->capability;
- mdev->opened = 0;
- snd_use_lock_init(&mdev->use_lock);
-
- /* copy and truncate the name of synth device */
- strlcpy(mdev->name, pinfo->name, sizeof(mdev->name));
-
- /* create MIDI coder */
- if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
- snd_printk(KERN_ERR "can't malloc midi coder\n");
- kfree(mdev);
- return -ENOMEM;
- }
- /* OSS sequencer adds running status to all sequences */
- snd_midi_event_no_status(mdev->coder, 1);
-
- /*
- * look for en empty slot
- */
- spin_lock_irqsave(&register_lock, flags);
- for (i = 0; i < max_midi_devs; i++) {
- if (midi_devs[i] == NULL)
- break;
- }
- if (i >= max_midi_devs) {
- if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
- spin_unlock_irqrestore(&register_lock, flags);
- snd_midi_event_free(mdev->coder);
- kfree(mdev);
- return -ENOMEM;
- }
- max_midi_devs++;
- }
- mdev->seq_device = i;
- midi_devs[mdev->seq_device] = mdev;
- spin_unlock_irqrestore(&register_lock, flags);
-
- return 0;
-}
-
-/*
- * release the midi device if it was registered
- */
-int
-snd_seq_oss_midi_check_exit_port(int client, int port)
-{
- struct seq_oss_midi *mdev;
- unsigned long flags;
- int index;
-
- if ((mdev = find_slot(client, port)) != NULL) {
- spin_lock_irqsave(&register_lock, flags);
- midi_devs[mdev->seq_device] = NULL;
- spin_unlock_irqrestore(&register_lock, flags);
- snd_use_lock_free(&mdev->use_lock);
- snd_use_lock_sync(&mdev->use_lock);
- if (mdev->coder)
- snd_midi_event_free(mdev->coder);
- kfree(mdev);
- }
- spin_lock_irqsave(&register_lock, flags);
- for (index = max_midi_devs - 1; index >= 0; index--) {
- if (midi_devs[index])
- break;
- }
- max_midi_devs = index + 1;
- spin_unlock_irqrestore(&register_lock, flags);
- return 0;
-}
-
-
-/*
- * release the midi device if it was registered
- */
-void
-snd_seq_oss_midi_clear_all(void)
-{
- int i;
- struct seq_oss_midi *mdev;
- unsigned long flags;
-
- spin_lock_irqsave(&register_lock, flags);
- for (i = 0; i < max_midi_devs; i++) {
- if ((mdev = midi_devs[i]) != NULL) {
- if (mdev->coder)
- snd_midi_event_free(mdev->coder);
- kfree(mdev);
- midi_devs[i] = NULL;
- }
- }
- max_midi_devs = 0;
- spin_unlock_irqrestore(&register_lock, flags);
-}
-
-
-/*
- * set up midi tables
- */
-void
-snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
-{
- dp->max_mididev = max_midi_devs;
-}
-
-/*
- * clean up midi tables
- */
-void
-snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp)
-{
- int i;
- for (i = 0; i < dp->max_mididev; i++)
- snd_seq_oss_midi_close(dp, i);
- dp->max_mididev = 0;
-}
-
-
-/*
- * open all midi devices. ignore errors.
- */
-void
-snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode)
-{
- int i;
- for (i = 0; i < dp->max_mididev; i++)
- snd_seq_oss_midi_open(dp, i, file_mode);
-}
-
-
-/*
- * get the midi device information
- */
-static struct seq_oss_midi *
-get_mididev(struct seq_oss_devinfo *dp, int dev)
-{
- if (dev < 0 || dev >= dp->max_mididev)
- return NULL;
- return get_mdev(dev);
-}
-
-
-/*
- * open the midi device if not opened yet
- */
-int
-snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
-{
- int perm;
- struct seq_oss_midi *mdev;
- struct snd_seq_port_subscribe subs;
-
- if ((mdev = get_mididev(dp, dev)) == NULL)
- return -ENODEV;
-
- /* already used? */
- if (mdev->opened && mdev->devinfo != dp) {
- snd_use_lock_free(&mdev->use_lock);
- return -EBUSY;
- }
-
- perm = 0;
- if (is_write_mode(fmode))
- perm |= PERM_WRITE;
- if (is_read_mode(fmode))
- perm |= PERM_READ;
- perm &= mdev->flags;
- if (perm == 0) {
- snd_use_lock_free(&mdev->use_lock);
- return -ENXIO;
- }
-
- /* already opened? */
- if ((mdev->opened & perm) == perm) {
- snd_use_lock_free(&mdev->use_lock);
- return 0;
- }
-
- perm &= ~mdev->opened;
-
- memset(&subs, 0, sizeof(subs));
-
- if (perm & PERM_WRITE) {
- subs.sender = dp->addr;
- subs.dest.client = mdev->client;
- subs.dest.port = mdev->port;
- if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
- mdev->opened |= PERM_WRITE;
- }
- if (perm & PERM_READ) {
- subs.sender.client = mdev->client;
- subs.sender.port = mdev->port;
- subs.dest = dp->addr;
- subs.flags = SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
- subs.queue = dp->queue; /* queue for timestamps */
- if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
- mdev->opened |= PERM_READ;
- }
-
- if (! mdev->opened) {
- snd_use_lock_free(&mdev->use_lock);
- return -ENXIO;
- }
-
- mdev->devinfo = dp;
- snd_use_lock_free(&mdev->use_lock);
- return 0;
-}
-
-/*
- * close the midi device if already opened
- */
-int
-snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
-{
- struct seq_oss_midi *mdev;
- struct snd_seq_port_subscribe subs;
-
- if ((mdev = get_mididev(dp, dev)) == NULL)
- return -ENODEV;
- if (! mdev->opened || mdev->devinfo != dp) {
- snd_use_lock_free(&mdev->use_lock);
- return 0;
- }
-
- debug_printk(("closing client %d port %d mode %d\n", mdev->client, mdev->port, mdev->opened));
- memset(&subs, 0, sizeof(subs));
- if (mdev->opened & PERM_WRITE) {
- subs.sender = dp->addr;
- subs.dest.client = mdev->client;
- subs.dest.port = mdev->port;
- snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
- }
- if (mdev->opened & PERM_READ) {
- subs.sender.client = mdev->client;
- subs.sender.port = mdev->port;
- subs.dest = dp->addr;
- snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
- }
-
- mdev->opened = 0;
- mdev->devinfo = NULL;
-
- snd_use_lock_free(&mdev->use_lock);
- return 0;
-}
-
-/*
- * change seq capability flags to file mode flags
- */
-int
-snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
-{
- struct seq_oss_midi *mdev;
- int mode;
-
- if ((mdev = get_mididev(dp, dev)) == NULL)
- return 0;
-
- mode = 0;
- if (mdev->opened & PERM_WRITE)
- mode |= SNDRV_SEQ_OSS_FILE_WRITE;
- if (mdev->opened & PERM_READ)
- mode |= SNDRV_SEQ_OSS_FILE_READ;
-
- snd_use_lock_free(&mdev->use_lock);
- return mode;
-}
-
-/*
- * reset the midi device and close it:
- * so far, only close the device.
- */
-void
-snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
-{
- struct seq_oss_midi *mdev;
-
- if ((mdev = get_mididev(dp, dev)) == NULL)
- return;
- if (! mdev->opened) {
- snd_use_lock_free(&mdev->use_lock);
- return;
- }
-
- if (mdev->opened & PERM_WRITE) {
- struct snd_seq_event ev;
- int c;
-
- debug_printk(("resetting client %d port %d\n", mdev->client, mdev->port));
- memset(&ev, 0, sizeof(ev));
- ev.dest.client = mdev->client;
- ev.dest.port = mdev->port;
- ev.queue = dp->queue;
- ev.source.port = dp->port;
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) {
- ev.type = SNDRV_SEQ_EVENT_SENSING;
- snd_seq_oss_dispatch(dp, &ev, 0, 0);
- }
- for (c = 0; c < 16; c++) {
- ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
- ev.data.control.channel = c;
- ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF;
- snd_seq_oss_dispatch(dp, &ev, 0, 0);
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
- ev.data.control.param =
- MIDI_CTL_RESET_CONTROLLERS;
- snd_seq_oss_dispatch(dp, &ev, 0, 0);
- ev.type = SNDRV_SEQ_EVENT_PITCHBEND;
- ev.data.control.value = 0;
- snd_seq_oss_dispatch(dp, &ev, 0, 0);
- }
- }
- }
- // snd_seq_oss_midi_close(dp, dev);
- snd_use_lock_free(&mdev->use_lock);
-}
-
-
-/*
- * get client/port of the specified MIDI device
- */
-void
-snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr)
-{
- struct seq_oss_midi *mdev;
-
- if ((mdev = get_mididev(dp, dev)) == NULL)
- return;
- addr->client = mdev->client;
- addr->port = mdev->port;
- snd_use_lock_free(&mdev->use_lock);
-}
-
-
-/*
- * input callback - this can be atomic
- */
-int
-snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
-{
- struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
- struct seq_oss_midi *mdev;
- int rc;
-
- if (dp->readq == NULL)
- return 0;
- if ((mdev = find_slot(ev->source.client, ev->source.port)) == NULL)
- return 0;
- if (! (mdev->opened & PERM_READ)) {
- snd_use_lock_free(&mdev->use_lock);
- return 0;
- }
-
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
- rc = send_synth_event(dp, ev, mdev->seq_device);
- else
- rc = send_midi_event(dp, ev, mdev);
-
- snd_use_lock_free(&mdev->use_lock);
- return rc;
-}
-
-/*
- * convert ALSA sequencer event to OSS synth event
- */
-static int
-send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev)
-{
- union evrec ossev;
-
- memset(&ossev, 0, sizeof(ossev));
-
- switch (ev->type) {
- case SNDRV_SEQ_EVENT_NOTEON:
- ossev.v.cmd = MIDI_NOTEON; break;
- case SNDRV_SEQ_EVENT_NOTEOFF:
- ossev.v.cmd = MIDI_NOTEOFF; break;
- case SNDRV_SEQ_EVENT_KEYPRESS:
- ossev.v.cmd = MIDI_KEY_PRESSURE; break;
- case SNDRV_SEQ_EVENT_CONTROLLER:
- ossev.l.cmd = MIDI_CTL_CHANGE; break;
- case SNDRV_SEQ_EVENT_PGMCHANGE:
- ossev.l.cmd = MIDI_PGM_CHANGE; break;
- case SNDRV_SEQ_EVENT_CHANPRESS:
- ossev.l.cmd = MIDI_CHN_PRESSURE; break;
- case SNDRV_SEQ_EVENT_PITCHBEND:
- ossev.l.cmd = MIDI_PITCH_BEND; break;
- default:
- return 0; /* not supported */
- }
-
- ossev.v.dev = dev;
-
- switch (ev->type) {
- case SNDRV_SEQ_EVENT_NOTEON:
- case SNDRV_SEQ_EVENT_NOTEOFF:
- case SNDRV_SEQ_EVENT_KEYPRESS:
- ossev.v.code = EV_CHN_VOICE;
- ossev.v.note = ev->data.note.note;
- ossev.v.parm = ev->data.note.velocity;
- ossev.v.chn = ev->data.note.channel;
- break;
- case SNDRV_SEQ_EVENT_CONTROLLER:
- case SNDRV_SEQ_EVENT_PGMCHANGE:
- case SNDRV_SEQ_EVENT_CHANPRESS:
- ossev.l.code = EV_CHN_COMMON;
- ossev.l.p1 = ev->data.control.param;
- ossev.l.val = ev->data.control.value;
- ossev.l.chn = ev->data.control.channel;
- break;
- case SNDRV_SEQ_EVENT_PITCHBEND:
- ossev.l.code = EV_CHN_COMMON;
- ossev.l.val = ev->data.control.value + 8192;
- ossev.l.chn = ev->data.control.channel;
- break;
- }
-
- snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode);
- snd_seq_oss_readq_put_event(dp->readq, &ossev);
-
- return 0;
-}
-
-/*
- * decode event and send MIDI bytes to read queue
- */
-static int
-send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev)
-{
- char msg[32];
- int len;
-
- snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode);
- if (!dp->timer->running)
- len = snd_seq_oss_timer_start(dp->timer);
- if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
- if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
- snd_seq_oss_readq_puts(dp->readq, mdev->seq_device,
- ev->data.ext.ptr, ev->data.ext.len);
- } else {
- len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev);
- if (len > 0)
- snd_seq_oss_readq_puts(dp->readq, mdev->seq_device, msg, len);
- }
-
- return 0;
-}
-
-
-/*
- * dump midi data
- * return 0 : enqueued
- * non-zero : invalid - ignored
- */
-int
-snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
-{
- struct seq_oss_midi *mdev;
-
- if ((mdev = get_mididev(dp, dev)) == NULL)
- return -ENODEV;
- if (snd_midi_event_encode_byte(mdev->coder, c, ev) > 0) {
- snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
- snd_use_lock_free(&mdev->use_lock);
- return 0;
- }
- snd_use_lock_free(&mdev->use_lock);
- return -EINVAL;
-}
-
-/*
- * create OSS compatible midi_info record
- */
-int
-snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf)
-{
- struct seq_oss_midi *mdev;
-
- if ((mdev = get_mididev(dp, dev)) == NULL)
- return -ENXIO;
- inf->device = dev;
- inf->dev_type = 0; /* FIXME: ?? */
- inf->capabilities = 0; /* FIXME: ?? */
- strlcpy(inf->name, mdev->name, sizeof(inf->name));
- snd_use_lock_free(&mdev->use_lock);
- return 0;
-}
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * proc interface
- */
-static char *
-capmode_str(int val)
-{
- val &= PERM_READ|PERM_WRITE;
- if (val == (PERM_READ|PERM_WRITE))
- return "read/write";
- else if (val == PERM_READ)
- return "read";
- else if (val == PERM_WRITE)
- return "write";
- else
- return "none";
-}
-
-void
-snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
-{
- int i;
- struct seq_oss_midi *mdev;
-
- snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs);
- for (i = 0; i < max_midi_devs; i++) {
- snd_iprintf(buf, "\nmidi %d: ", i);
- mdev = get_mdev(i);
- if (mdev == NULL) {
- snd_iprintf(buf, "*empty*\n");
- continue;
- }
- snd_iprintf(buf, "[%s] ALSA port %d:%d\n", mdev->name,
- mdev->client, mdev->port);
- snd_iprintf(buf, " capability %s / opened %s\n",
- capmode_str(mdev->flags),
- capmode_str(mdev->opened));
- snd_use_lock_free(&mdev->use_lock);
- }
-}
-#endif /* CONFIG_PROC_FS */
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.h
deleted file mode 100644
index 84eb866b..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * midi device information
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __SEQ_OSS_MIDI_H
-#define __SEQ_OSS_MIDI_H
-
-#include "seq_oss_device.h"
-#include <sound/seq_oss_legacy.h>
-
-int snd_seq_oss_midi_lookup_ports(int client);
-int snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo);
-int snd_seq_oss_midi_check_exit_port(int client, int port);
-void snd_seq_oss_midi_clear_all(void);
-
-void snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp);
-void snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp);
-
-int snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int file_mode);
-void snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode);
-int snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev);
-void snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev);
-int snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c,
- struct snd_seq_event *ev);
-int snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private);
-int snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev);
-int snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf);
-void snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr);
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.c
deleted file mode 100644
index 73661c4a..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * seq_oss_readq.c - MIDI input queue
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "seq_oss_readq.h"
-#include "seq_oss_event.h"
-#include <sound/seq_oss_legacy.h>
-#include "../seq_lock.h"
-#include <linux/wait.h>
-#include <linux/slab.h>
-
-/*
- * constants
- */
-//#define SNDRV_SEQ_OSS_MAX_TIMEOUT (unsigned long)(-1)
-#define SNDRV_SEQ_OSS_MAX_TIMEOUT (HZ * 3600)
-
-
-/*
- * prototypes
- */
-
-
-/*
- * create a read queue
- */
-struct seq_oss_readq *
-snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen)
-{
- struct seq_oss_readq *q;
-
- if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) {
- snd_printk(KERN_ERR "can't malloc read queue\n");
- return NULL;
- }
-
- if ((q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL)) == NULL) {
- snd_printk(KERN_ERR "can't malloc read queue buffer\n");
- kfree(q);
- return NULL;
- }
-
- q->maxlen = maxlen;
- q->qlen = 0;
- q->head = q->tail = 0;
- init_waitqueue_head(&q->midi_sleep);
- spin_lock_init(&q->lock);
- q->pre_event_timeout = SNDRV_SEQ_OSS_MAX_TIMEOUT;
- q->input_time = (unsigned long)-1;
-
- return q;
-}
-
-/*
- * delete the read queue
- */
-void
-snd_seq_oss_readq_delete(struct seq_oss_readq *q)
-{
- if (q) {
- kfree(q->q);
- kfree(q);
- }
-}
-
-/*
- * reset the read queue
- */
-void
-snd_seq_oss_readq_clear(struct seq_oss_readq *q)
-{
- if (q->qlen) {
- q->qlen = 0;
- q->head = q->tail = 0;
- }
- /* if someone sleeping, wake'em up */
- if (waitqueue_active(&q->midi_sleep))
- wake_up(&q->midi_sleep);
- q->input_time = (unsigned long)-1;
-}
-
-/*
- * put a midi byte
- */
-int
-snd_seq_oss_readq_puts(struct seq_oss_readq *q, int dev, unsigned char *data, int len)
-{
- union evrec rec;
- int result;
-
- memset(&rec, 0, sizeof(rec));
- rec.c[0] = SEQ_MIDIPUTC;
- rec.c[2] = dev;
-
- while (len-- > 0) {
- rec.c[1] = *data++;
- result = snd_seq_oss_readq_put_event(q, &rec);
- if (result < 0)
- return result;
- }
- return 0;
-}
-
-/*
- * copy an event to input queue:
- * return zero if enqueued
- */
-int
-snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&q->lock, flags);
- if (q->qlen >= q->maxlen - 1) {
- spin_unlock_irqrestore(&q->lock, flags);
- return -ENOMEM;
- }
-
- memcpy(&q->q[q->tail], ev, sizeof(*ev));
- q->tail = (q->tail + 1) % q->maxlen;
- q->qlen++;
-
- /* wake up sleeper */
- if (waitqueue_active(&q->midi_sleep))
- wake_up(&q->midi_sleep);
-
- spin_unlock_irqrestore(&q->lock, flags);
-
- return 0;
-}
-
-
-/*
- * pop queue
- * caller must hold lock
- */
-int
-snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec)
-{
- if (q->qlen == 0)
- return -EAGAIN;
- memcpy(rec, &q->q[q->head], sizeof(*rec));
- return 0;
-}
-
-/*
- * sleep until ready
- */
-void
-snd_seq_oss_readq_wait(struct seq_oss_readq *q)
-{
- wait_event_interruptible_timeout(q->midi_sleep,
- (q->qlen > 0 || q->head == q->tail),
- q->pre_event_timeout);
-}
-
-/*
- * drain one record
- * caller must hold lock
- */
-void
-snd_seq_oss_readq_free(struct seq_oss_readq *q)
-{
- if (q->qlen > 0) {
- q->head = (q->head + 1) % q->maxlen;
- q->qlen--;
- }
-}
-
-/*
- * polling/select:
- * return non-zero if readq is not empty.
- */
-unsigned int
-snd_seq_oss_readq_poll(struct seq_oss_readq *q, struct file *file, poll_table *wait)
-{
- poll_wait(file, &q->midi_sleep, wait);
- return q->qlen;
-}
-
-/*
- * put a timestamp
- */
-int
-snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *q, unsigned long curt, int seq_mode)
-{
- if (curt != q->input_time) {
- union evrec rec;
- memset(&rec, 0, sizeof(rec));
- switch (seq_mode) {
- case SNDRV_SEQ_OSS_MODE_SYNTH:
- rec.echo = (curt << 8) | SEQ_WAIT;
- snd_seq_oss_readq_put_event(q, &rec);
- break;
- case SNDRV_SEQ_OSS_MODE_MUSIC:
- rec.t.code = EV_TIMING;
- rec.t.cmd = TMR_WAIT_ABS;
- rec.t.time = curt;
- snd_seq_oss_readq_put_event(q, &rec);
- break;
- }
- q->input_time = curt;
- }
- return 0;
-}
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * proc interface
- */
-void
-snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf)
-{
- snd_iprintf(buf, " read queue [%s] length = %d : tick = %ld\n",
- (waitqueue_active(&q->midi_sleep) ? "sleeping":"running"),
- q->qlen, q->input_time);
-}
-#endif /* CONFIG_PROC_FS */
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.h
deleted file mode 100644
index f1463f1f..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * OSS compatible sequencer driver
- * read fifo queue
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __SEQ_OSS_READQ_H
-#define __SEQ_OSS_READQ_H
-
-#include "seq_oss_device.h"
-
-
-/*
- * definition of read queue
- */
-struct seq_oss_readq {
- union evrec *q;
- int qlen;
- int maxlen;
- int head, tail;
- unsigned long pre_event_timeout;
- unsigned long input_time;
- wait_queue_head_t midi_sleep;
- spinlock_t lock;
-};
-
-struct seq_oss_readq *snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen);
-void snd_seq_oss_readq_delete(struct seq_oss_readq *q);
-void snd_seq_oss_readq_clear(struct seq_oss_readq *readq);
-unsigned int snd_seq_oss_readq_poll(struct seq_oss_readq *readq, struct file *file, poll_table *wait);
-int snd_seq_oss_readq_puts(struct seq_oss_readq *readq, int dev, unsigned char *data, int len);
-int snd_seq_oss_readq_put_event(struct seq_oss_readq *readq, union evrec *ev);
-int snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *readq, unsigned long curt, int seq_mode);
-int snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec);
-void snd_seq_oss_readq_wait(struct seq_oss_readq *q);
-void snd_seq_oss_readq_free(struct seq_oss_readq *q);
-
-#define snd_seq_oss_readq_lock(q, flags) spin_lock_irqsave(&(q)->lock, flags)
-#define snd_seq_oss_readq_unlock(q, flags) spin_unlock_irqrestore(&(q)->lock, flags)
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_rw.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_rw.c
deleted file mode 100644
index 6a7b6ace..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_rw.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * read/write/select interface to device file
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "seq_oss_device.h"
-#include "seq_oss_readq.h"
-#include "seq_oss_writeq.h"
-#include "seq_oss_synth.h"
-#include <sound/seq_oss_legacy.h>
-#include "seq_oss_event.h"
-#include "seq_oss_timer.h"
-#include "../seq_clientmgr.h"
-
-
-/*
- * protoypes
- */
-static int insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt);
-
-
-/*
- * read interface
- */
-
-int
-snd_seq_oss_read(struct seq_oss_devinfo *dp, char __user *buf, int count)
-{
- struct seq_oss_readq *readq = dp->readq;
- int result = 0, err = 0;
- int ev_len;
- union evrec rec;
- unsigned long flags;
-
- if (readq == NULL || ! is_read_mode(dp->file_mode))
- return -ENXIO;
-
- while (count >= SHORT_EVENT_SIZE) {
- snd_seq_oss_readq_lock(readq, flags);
- err = snd_seq_oss_readq_pick(readq, &rec);
- if (err == -EAGAIN &&
- !is_nonblock_mode(dp->file_mode) && result == 0) {
- snd_seq_oss_readq_unlock(readq, flags);
- snd_seq_oss_readq_wait(readq);
- snd_seq_oss_readq_lock(readq, flags);
- if (signal_pending(current))
- err = -ERESTARTSYS;
- else
- err = snd_seq_oss_readq_pick(readq, &rec);
- }
- if (err < 0) {
- snd_seq_oss_readq_unlock(readq, flags);
- break;
- }
- ev_len = ev_length(&rec);
- if (ev_len < count) {
- snd_seq_oss_readq_unlock(readq, flags);
- break;
- }
- snd_seq_oss_readq_free(readq);
- snd_seq_oss_readq_unlock(readq, flags);
- if (copy_to_user(buf, &rec, ev_len)) {
- err = -EFAULT;
- break;
- }
- result += ev_len;
- buf += ev_len;
- count -= ev_len;
- }
- return result > 0 ? result : err;
-}
-
-
-/*
- * write interface
- */
-
-int
-snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count, struct file *opt)
-{
- int result = 0, err = 0;
- int ev_size, fmt;
- union evrec rec;
-
- if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
- return -ENXIO;
-
- while (count >= SHORT_EVENT_SIZE) {
- if (copy_from_user(&rec, buf, SHORT_EVENT_SIZE)) {
- err = -EFAULT;
- break;
- }
- if (rec.s.code == SEQ_FULLSIZE) {
- /* load patch */
- if (result > 0) {
- err = -EINVAL;
- break;
- }
- fmt = (*(unsigned short *)rec.c) & 0xffff;
- /* FIXME the return value isn't correct */
- return snd_seq_oss_synth_load_patch(dp, rec.s.dev,
- fmt, buf, 0, count);
- }
- if (ev_is_long(&rec)) {
- /* extended code */
- if (rec.s.code == SEQ_EXTENDED &&
- dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
- err = -EINVAL;
- break;
- }
- ev_size = LONG_EVENT_SIZE;
- if (count < ev_size)
- break;
- /* copy the reset 4 bytes */
- if (copy_from_user(rec.c + SHORT_EVENT_SIZE,
- buf + SHORT_EVENT_SIZE,
- LONG_EVENT_SIZE - SHORT_EVENT_SIZE)) {
- err = -EFAULT;
- break;
- }
- } else {
- /* old-type code */
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
- err = -EINVAL;
- break;
- }
- ev_size = SHORT_EVENT_SIZE;
- }
-
- /* insert queue */
- if ((err = insert_queue(dp, &rec, opt)) < 0)
- break;
-
- result += ev_size;
- buf += ev_size;
- count -= ev_size;
- }
- return result > 0 ? result : err;
-}
-
-
-/*
- * insert event record to write queue
- * return: 0 = OK, non-zero = NG
- */
-static int
-insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt)
-{
- int rc = 0;
- struct snd_seq_event event;
-
- /* if this is a timing event, process the current time */
- if (snd_seq_oss_process_timer_event(dp->timer, rec))
- return 0; /* no need to insert queue */
-
- /* parse this event */
- memset(&event, 0, sizeof(event));
- /* set dummy -- to be sure */
- event.type = SNDRV_SEQ_EVENT_NOTEOFF;
- snd_seq_oss_fill_addr(dp, &event, dp->addr.port, dp->addr.client);
-
- if (snd_seq_oss_process_event(dp, rec, &event))
- return 0; /* invalid event - no need to insert queue */
-
- event.time.tick = snd_seq_oss_timer_cur_tick(dp->timer);
- if (dp->timer->realtime || !dp->timer->running) {
- snd_seq_oss_dispatch(dp, &event, 0, 0);
- } else {
- if (is_nonblock_mode(dp->file_mode))
- rc = snd_seq_kernel_client_enqueue(dp->cseq, &event, 0, 0);
- else
- rc = snd_seq_kernel_client_enqueue_blocking(dp->cseq, &event, opt, 0, 0);
- }
- return rc;
-}
-
-
-/*
- * select / poll
- */
-
-unsigned int
-snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait)
-{
- unsigned int mask = 0;
-
- /* input */
- if (dp->readq && is_read_mode(dp->file_mode)) {
- if (snd_seq_oss_readq_poll(dp->readq, file, wait))
- mask |= POLLIN | POLLRDNORM;
- }
-
- /* output */
- if (dp->writeq && is_write_mode(dp->file_mode)) {
- if (snd_seq_kernel_client_write_poll(dp->cseq, file, wait))
- mask |= POLLOUT | POLLWRNORM;
- }
- return mask;
-}
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.c
deleted file mode 100644
index c5b773a1..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.c
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * synth device handlers
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "seq_oss_synth.h"
-#include "seq_oss_midi.h"
-#include "../seq_lock.h"
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-/*
- * constants
- */
-#define SNDRV_SEQ_OSS_MAX_SYNTH_NAME 30
-#define MAX_SYSEX_BUFLEN 128
-
-
-/*
- * definition of synth info records
- */
-
-/* sysex buffer */
-struct seq_oss_synth_sysex {
- int len;
- int skip;
- unsigned char buf[MAX_SYSEX_BUFLEN];
-};
-
-/* synth info */
-struct seq_oss_synth {
- int seq_device;
-
- /* for synth_info */
- int synth_type;
- int synth_subtype;
- int nr_voices;
-
- char name[SNDRV_SEQ_OSS_MAX_SYNTH_NAME];
- struct snd_seq_oss_callback oper;
-
- int opened;
-
- void *private_data;
- snd_use_lock_t use_lock;
-};
-
-
-/*
- * device table
- */
-static int max_synth_devs;
-static struct seq_oss_synth *synth_devs[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
-static struct seq_oss_synth midi_synth_dev = {
- -1, /* seq_device */
- SYNTH_TYPE_MIDI, /* synth_type */
- 0, /* synth_subtype */
- 16, /* nr_voices */
- "MIDI", /* name */
-};
-
-static DEFINE_SPINLOCK(register_lock);
-
-/*
- * prototypes
- */
-static struct seq_oss_synth *get_synthdev(struct seq_oss_devinfo *dp, int dev);
-static void reset_channels(struct seq_oss_synthinfo *info);
-
-/*
- * global initialization
- */
-void __init
-snd_seq_oss_synth_init(void)
-{
- snd_use_lock_init(&midi_synth_dev.use_lock);
-}
-
-/*
- * registration of the synth device
- */
-int
-snd_seq_oss_synth_register(struct snd_seq_device *dev)
-{
- int i;
- struct seq_oss_synth *rec;
- struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
- unsigned long flags;
-
- if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
- snd_printk(KERN_ERR "can't malloc synth info\n");
- return -ENOMEM;
- }
- rec->seq_device = -1;
- rec->synth_type = reg->type;
- rec->synth_subtype = reg->subtype;
- rec->nr_voices = reg->nvoices;
- rec->oper = reg->oper;
- rec->private_data = reg->private_data;
- rec->opened = 0;
- snd_use_lock_init(&rec->use_lock);
-
- /* copy and truncate the name of synth device */
- strlcpy(rec->name, dev->name, sizeof(rec->name));
-
- /* registration */
- spin_lock_irqsave(&register_lock, flags);
- for (i = 0; i < max_synth_devs; i++) {
- if (synth_devs[i] == NULL)
- break;
- }
- if (i >= max_synth_devs) {
- if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
- spin_unlock_irqrestore(&register_lock, flags);
- snd_printk(KERN_ERR "no more synth slot\n");
- kfree(rec);
- return -ENOMEM;
- }
- max_synth_devs++;
- }
- rec->seq_device = i;
- synth_devs[i] = rec;
- debug_printk(("synth %s registered %d\n", rec->name, i));
- spin_unlock_irqrestore(&register_lock, flags);
- dev->driver_data = rec;
-#ifdef SNDRV_OSS_INFO_DEV_SYNTH
- if (i < SNDRV_CARDS)
- snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name);
-#endif
- return 0;
-}
-
-
-int
-snd_seq_oss_synth_unregister(struct snd_seq_device *dev)
-{
- int index;
- struct seq_oss_synth *rec = dev->driver_data;
- unsigned long flags;
-
- spin_lock_irqsave(&register_lock, flags);
- for (index = 0; index < max_synth_devs; index++) {
- if (synth_devs[index] == rec)
- break;
- }
- if (index >= max_synth_devs) {
- spin_unlock_irqrestore(&register_lock, flags);
- snd_printk(KERN_ERR "can't unregister synth\n");
- return -EINVAL;
- }
- synth_devs[index] = NULL;
- if (index == max_synth_devs - 1) {
- for (index--; index >= 0; index--) {
- if (synth_devs[index])
- break;
- }
- max_synth_devs = index + 1;
- }
- spin_unlock_irqrestore(&register_lock, flags);
-#ifdef SNDRV_OSS_INFO_DEV_SYNTH
- if (rec->seq_device < SNDRV_CARDS)
- snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device);
-#endif
-
- snd_use_lock_sync(&rec->use_lock);
- kfree(rec);
-
- return 0;
-}
-
-
-/*
- */
-static struct seq_oss_synth *
-get_sdev(int dev)
-{
- struct seq_oss_synth *rec;
- unsigned long flags;
-
- spin_lock_irqsave(&register_lock, flags);
- rec = synth_devs[dev];
- if (rec)
- snd_use_lock_use(&rec->use_lock);
- spin_unlock_irqrestore(&register_lock, flags);
- return rec;
-}
-
-
-/*
- * set up synth tables
- */
-
-void
-snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
-{
- int i;
- struct seq_oss_synth *rec;
- struct seq_oss_synthinfo *info;
-
- dp->max_synthdev = max_synth_devs;
- dp->synth_opened = 0;
- memset(dp->synths, 0, sizeof(dp->synths));
- for (i = 0; i < dp->max_synthdev; i++) {
- rec = get_sdev(i);
- if (rec == NULL)
- continue;
- if (rec->oper.open == NULL || rec->oper.close == NULL) {
- snd_use_lock_free(&rec->use_lock);
- continue;
- }
- info = &dp->synths[i];
- info->arg.app_index = dp->port;
- info->arg.file_mode = dp->file_mode;
- info->arg.seq_mode = dp->seq_mode;
- if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH)
- info->arg.event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS;
- else
- info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
- info->opened = 0;
- if (!try_module_get(rec->oper.owner)) {
- snd_use_lock_free(&rec->use_lock);
- continue;
- }
- if (rec->oper.open(&info->arg, rec->private_data) < 0) {
- module_put(rec->oper.owner);
- snd_use_lock_free(&rec->use_lock);
- continue;
- }
- info->nr_voices = rec->nr_voices;
- if (info->nr_voices > 0) {
- info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
- if (!info->ch) {
- snd_printk(KERN_ERR "Cannot malloc\n");
- rec->oper.close(&info->arg);
- module_put(rec->oper.owner);
- snd_use_lock_free(&rec->use_lock);
- continue;
- }
- reset_channels(info);
- }
- debug_printk(("synth %d assigned\n", i));
- info->opened++;
- rec->opened++;
- dp->synth_opened++;
- snd_use_lock_free(&rec->use_lock);
- }
-}
-
-
-/*
- * set up synth tables for MIDI emulation - /dev/music mode only
- */
-
-void
-snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp)
-{
- int i;
-
- if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
- return;
-
- for (i = 0; i < dp->max_mididev; i++) {
- struct seq_oss_synthinfo *info;
- info = &dp->synths[dp->max_synthdev];
- if (snd_seq_oss_midi_open(dp, i, dp->file_mode) < 0)
- continue;
- info->arg.app_index = dp->port;
- info->arg.file_mode = dp->file_mode;
- info->arg.seq_mode = dp->seq_mode;
- info->arg.private_data = info;
- info->is_midi = 1;
- info->midi_mapped = i;
- info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
- snd_seq_oss_midi_get_addr(dp, i, &info->arg.addr);
- info->opened = 1;
- midi_synth_dev.opened++;
- dp->max_synthdev++;
- if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
- break;
- }
-}
-
-
-/*
- * clean up synth tables
- */
-
-void
-snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
-{
- int i;
- struct seq_oss_synth *rec;
- struct seq_oss_synthinfo *info;
-
- if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
- return;
- for (i = 0; i < dp->max_synthdev; i++) {
- info = &dp->synths[i];
- if (! info->opened)
- continue;
- if (info->is_midi) {
- if (midi_synth_dev.opened > 0) {
- snd_seq_oss_midi_close(dp, info->midi_mapped);
- midi_synth_dev.opened--;
- }
- } else {
- rec = get_sdev(i);
- if (rec == NULL)
- continue;
- if (rec->opened > 0) {
- debug_printk(("synth %d closed\n", i));
- rec->oper.close(&info->arg);
- module_put(rec->oper.owner);
- rec->opened = 0;
- }
- snd_use_lock_free(&rec->use_lock);
- }
- kfree(info->sysex);
- info->sysex = NULL;
- kfree(info->ch);
- info->ch = NULL;
- }
- dp->synth_opened = 0;
- dp->max_synthdev = 0;
-}
-
-/*
- * check if the specified device is MIDI mapped device
- */
-static int
-is_midi_dev(struct seq_oss_devinfo *dp, int dev)
-{
- if (dev < 0 || dev >= dp->max_synthdev)
- return 0;
- if (dp->synths[dev].is_midi)
- return 1;
- return 0;
-}
-
-/*
- * return synth device information pointer
- */
-static struct seq_oss_synth *
-get_synthdev(struct seq_oss_devinfo *dp, int dev)
-{
- struct seq_oss_synth *rec;
- if (dev < 0 || dev >= dp->max_synthdev)
- return NULL;
- if (! dp->synths[dev].opened)
- return NULL;
- if (dp->synths[dev].is_midi)
- return &midi_synth_dev;
- if ((rec = get_sdev(dev)) == NULL)
- return NULL;
- if (! rec->opened) {
- snd_use_lock_free(&rec->use_lock);
- return NULL;
- }
- return rec;
-}
-
-
-/*
- * reset note and velocity on each channel.
- */
-static void
-reset_channels(struct seq_oss_synthinfo *info)
-{
- int i;
- if (info->ch == NULL || ! info->nr_voices)
- return;
- for (i = 0; i < info->nr_voices; i++) {
- info->ch[i].note = -1;
- info->ch[i].vel = 0;
- }
-}
-
-
-/*
- * reset synth device:
- * call reset callback. if no callback is defined, send a heartbeat
- * event to the corresponding port.
- */
-void
-snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
-{
- struct seq_oss_synth *rec;
- struct seq_oss_synthinfo *info;
-
- if (snd_BUG_ON(dev < 0 || dev >= dp->max_synthdev))
- return;
- info = &dp->synths[dev];
- if (! info->opened)
- return;
- if (info->sysex)
- info->sysex->len = 0; /* reset sysex */
- reset_channels(info);
- if (info->is_midi) {
- if (midi_synth_dev.opened <= 0)
- return;
- snd_seq_oss_midi_reset(dp, info->midi_mapped);
- /* reopen the device */
- snd_seq_oss_midi_close(dp, dev);
- if (snd_seq_oss_midi_open(dp, info->midi_mapped,
- dp->file_mode) < 0) {
- midi_synth_dev.opened--;
- info->opened = 0;
- kfree(info->sysex);
- info->sysex = NULL;
- kfree(info->ch);
- info->ch = NULL;
- }
- return;
- }
-
- rec = get_sdev(dev);
- if (rec == NULL)
- return;
- if (rec->oper.reset) {
- rec->oper.reset(&info->arg);
- } else {
- struct snd_seq_event ev;
- memset(&ev, 0, sizeof(ev));
- snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client,
- info->arg.addr.port);
- ev.type = SNDRV_SEQ_EVENT_RESET;
- snd_seq_oss_dispatch(dp, &ev, 0, 0);
- }
- snd_use_lock_free(&rec->use_lock);
-}
-
-
-/*
- * load a patch record:
- * call load_patch callback function
- */
-int
-snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
- const char __user *buf, int p, int c)
-{
- struct seq_oss_synth *rec;
- int rc;
-
- if (dev < 0 || dev >= dp->max_synthdev)
- return -ENXIO;
-
- if (is_midi_dev(dp, dev))
- return 0;
- if ((rec = get_synthdev(dp, dev)) == NULL)
- return -ENXIO;
-
- if (rec->oper.load_patch == NULL)
- rc = -ENXIO;
- else
- rc = rec->oper.load_patch(&dp->synths[dev].arg, fmt, buf, p, c);
- snd_use_lock_free(&rec->use_lock);
- return rc;
-}
-
-/*
- * check if the device is valid synth device
- */
-int
-snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev)
-{
- struct seq_oss_synth *rec;
- rec = get_synthdev(dp, dev);
- if (rec) {
- snd_use_lock_free(&rec->use_lock);
- return 1;
- }
- return 0;
-}
-
-
-/*
- * receive OSS 6 byte sysex packet:
- * the full sysex message will be sent if it reaches to the end of data
- * (0xff).
- */
-int
-snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev)
-{
- int i, send;
- unsigned char *dest;
- struct seq_oss_synth_sysex *sysex;
-
- if (! snd_seq_oss_synth_is_valid(dp, dev))
- return -ENXIO;
-
- sysex = dp->synths[dev].sysex;
- if (sysex == NULL) {
- sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
- if (sysex == NULL)
- return -ENOMEM;
- dp->synths[dev].sysex = sysex;
- }
-
- send = 0;
- dest = sysex->buf + sysex->len;
- /* copy 6 byte packet to the buffer */
- for (i = 0; i < 6; i++) {
- if (buf[i] == 0xff) {
- send = 1;
- break;
- }
- dest[i] = buf[i];
- sysex->len++;
- if (sysex->len >= MAX_SYSEX_BUFLEN) {
- sysex->len = 0;
- sysex->skip = 1;
- break;
- }
- }
-
- if (sysex->len && send) {
- if (sysex->skip) {
- sysex->skip = 0;
- sysex->len = 0;
- return -EINVAL; /* skip */
- }
- /* copy the data to event record and send it */
- ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
- if (snd_seq_oss_synth_addr(dp, dev, ev))
- return -EINVAL;
- ev->data.ext.len = sysex->len;
- ev->data.ext.ptr = sysex->buf;
- sysex->len = 0;
- return 0;
- }
-
- return -EINVAL; /* skip */
-}
-
-/*
- * fill the event source/destination addresses
- */
-int
-snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev)
-{
- if (! snd_seq_oss_synth_is_valid(dp, dev))
- return -EINVAL;
- snd_seq_oss_fill_addr(dp, ev, dp->synths[dev].arg.addr.client,
- dp->synths[dev].arg.addr.port);
- return 0;
-}
-
-
-/*
- * OSS compatible ioctl
- */
-int
-snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
-{
- struct seq_oss_synth *rec;
- int rc;
-
- if (is_midi_dev(dp, dev))
- return -ENXIO;
- if ((rec = get_synthdev(dp, dev)) == NULL)
- return -ENXIO;
- if (rec->oper.ioctl == NULL)
- rc = -ENXIO;
- else
- rc = rec->oper.ioctl(&dp->synths[dev].arg, cmd, addr);
- snd_use_lock_free(&rec->use_lock);
- return rc;
-}
-
-
-/*
- * send OSS raw events - SEQ_PRIVATE and SEQ_VOLUME
- */
-int
-snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev)
-{
- if (! snd_seq_oss_synth_is_valid(dp, dev) || is_midi_dev(dp, dev))
- return -ENXIO;
- ev->type = SNDRV_SEQ_EVENT_OSS;
- memcpy(ev->data.raw8.d, data, 8);
- return snd_seq_oss_synth_addr(dp, dev, ev);
-}
-
-
-/*
- * create OSS compatible synth_info record
- */
-int
-snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf)
-{
- struct seq_oss_synth *rec;
-
- if (dev < 0 || dev >= dp->max_synthdev)
- return -ENXIO;
-
- if (dp->synths[dev].is_midi) {
- struct midi_info minf;
- snd_seq_oss_midi_make_info(dp, dp->synths[dev].midi_mapped, &minf);
- inf->synth_type = SYNTH_TYPE_MIDI;
- inf->synth_subtype = 0;
- inf->nr_voices = 16;
- inf->device = dev;
- strlcpy(inf->name, minf.name, sizeof(inf->name));
- } else {
- if ((rec = get_synthdev(dp, dev)) == NULL)
- return -ENXIO;
- inf->synth_type = rec->synth_type;
- inf->synth_subtype = rec->synth_subtype;
- inf->nr_voices = rec->nr_voices;
- inf->device = dev;
- strlcpy(inf->name, rec->name, sizeof(inf->name));
- snd_use_lock_free(&rec->use_lock);
- }
- return 0;
-}
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * proc interface
- */
-void
-snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
-{
- int i;
- struct seq_oss_synth *rec;
-
- snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
- for (i = 0; i < max_synth_devs; i++) {
- snd_iprintf(buf, "\nsynth %d: ", i);
- rec = get_sdev(i);
- if (rec == NULL) {
- snd_iprintf(buf, "*empty*\n");
- continue;
- }
- snd_iprintf(buf, "[%s]\n", rec->name);
- snd_iprintf(buf, " type 0x%x : subtype 0x%x : voices %d\n",
- rec->synth_type, rec->synth_subtype,
- rec->nr_voices);
- snd_iprintf(buf, " capabilities : ioctl %s / load_patch %s\n",
- enabled_str((long)rec->oper.ioctl),
- enabled_str((long)rec->oper.load_patch));
- snd_use_lock_free(&rec->use_lock);
- }
-}
-#endif /* CONFIG_PROC_FS */
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.h
deleted file mode 100644
index dbdfcbb8..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * synth device information
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __SEQ_OSS_SYNTH_H
-#define __SEQ_OSS_SYNTH_H
-
-#include "seq_oss_device.h"
-#include <sound/seq_oss_legacy.h>
-#include <sound/seq_device.h>
-
-void snd_seq_oss_synth_init(void);
-int snd_seq_oss_synth_register(struct snd_seq_device *dev);
-int snd_seq_oss_synth_unregister(struct snd_seq_device *dev);
-void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp);
-void snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp);
-void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp);
-
-void snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev);
-int snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
- const char __user *buf, int p, int c);
-int snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev);
-int snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf,
- struct snd_seq_event *ev);
-int snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev);
-int snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd,
- unsigned long addr);
-int snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev,
- unsigned char *data, struct snd_seq_event *ev);
-
-int snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf);
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.c
deleted file mode 100644
index ab59cbfb..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * Timer control routines
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "seq_oss_timer.h"
-#include "seq_oss_event.h"
-#include <sound/seq_oss_legacy.h>
-#include <linux/slab.h>
-
-/*
- */
-#define MIN_OSS_TEMPO 8
-#define MAX_OSS_TEMPO 360
-#define MIN_OSS_TIMEBASE 1
-#define MAX_OSS_TIMEBASE 1000
-
-/*
- */
-static void calc_alsa_tempo(struct seq_oss_timer *timer);
-static int send_timer_event(struct seq_oss_devinfo *dp, int type, int value);
-
-
-/*
- * create and register a new timer.
- * if queue is not started yet, start it.
- */
-struct seq_oss_timer *
-snd_seq_oss_timer_new(struct seq_oss_devinfo *dp)
-{
- struct seq_oss_timer *rec;
-
- rec = kzalloc(sizeof(*rec), GFP_KERNEL);
- if (rec == NULL)
- return NULL;
-
- rec->dp = dp;
- rec->cur_tick = 0;
- rec->realtime = 0;
- rec->running = 0;
- rec->oss_tempo = 60;
- rec->oss_timebase = 100;
- calc_alsa_tempo(rec);
-
- return rec;
-}
-
-
-/*
- * delete timer.
- * if no more timer exists, stop the queue.
- */
-void
-snd_seq_oss_timer_delete(struct seq_oss_timer *rec)
-{
- if (rec) {
- snd_seq_oss_timer_stop(rec);
- kfree(rec);
- }
-}
-
-
-/*
- * process one timing event
- * return 1 : event proceseed -- skip this event
- * 0 : not a timer event -- enqueue this event
- */
-int
-snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev)
-{
- abstime_t parm = ev->t.time;
-
- if (ev->t.code == EV_TIMING) {
- switch (ev->t.cmd) {
- case TMR_WAIT_REL:
- parm += rec->cur_tick;
- rec->realtime = 0;
- /* continue to next */
- case TMR_WAIT_ABS:
- if (parm == 0) {
- rec->realtime = 1;
- } else if (parm >= rec->cur_tick) {
- rec->realtime = 0;
- rec->cur_tick = parm;
- }
- return 1; /* skip this event */
-
- case TMR_START:
- snd_seq_oss_timer_start(rec);
- return 1;
-
- }
- } else if (ev->s.code == SEQ_WAIT) {
- /* time = from 1 to 3 bytes */
- parm = (ev->echo >> 8) & 0xffffff;
- if (parm > rec->cur_tick) {
- /* set next event time */
- rec->cur_tick = parm;
- rec->realtime = 0;
- }
- return 1;
- }
-
- return 0;
-}
-
-
-/*
- * convert tempo units
- */
-static void
-calc_alsa_tempo(struct seq_oss_timer *timer)
-{
- timer->tempo = (60 * 1000000) / timer->oss_tempo;
- timer->ppq = timer->oss_timebase;
-}
-
-
-/*
- * dispatch a timer event
- */
-static int
-send_timer_event(struct seq_oss_devinfo *dp, int type, int value)
-{
- struct snd_seq_event ev;
-
- memset(&ev, 0, sizeof(ev));
- ev.type = type;
- ev.source.client = dp->cseq;
- ev.source.port = 0;
- ev.dest.client = SNDRV_SEQ_CLIENT_SYSTEM;
- ev.dest.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
- ev.queue = dp->queue;
- ev.data.queue.queue = dp->queue;
- ev.data.queue.param.value = value;
- return snd_seq_kernel_client_dispatch(dp->cseq, &ev, 1, 0);
-}
-
-/*
- * set queue tempo and start queue
- */
-int
-snd_seq_oss_timer_start(struct seq_oss_timer *timer)
-{
- struct seq_oss_devinfo *dp = timer->dp;
- struct snd_seq_queue_tempo tmprec;
-
- if (timer->running)
- snd_seq_oss_timer_stop(timer);
-
- memset(&tmprec, 0, sizeof(tmprec));
- tmprec.queue = dp->queue;
- tmprec.ppq = timer->ppq;
- tmprec.tempo = timer->tempo;
- snd_seq_set_queue_tempo(dp->cseq, &tmprec);
-
- send_timer_event(dp, SNDRV_SEQ_EVENT_START, 0);
- timer->running = 1;
- timer->cur_tick = 0;
- return 0;
-}
-
-
-/*
- * stop queue
- */
-int
-snd_seq_oss_timer_stop(struct seq_oss_timer *timer)
-{
- if (! timer->running)
- return 0;
- send_timer_event(timer->dp, SNDRV_SEQ_EVENT_STOP, 0);
- timer->running = 0;
- return 0;
-}
-
-
-/*
- * continue queue
- */
-int
-snd_seq_oss_timer_continue(struct seq_oss_timer *timer)
-{
- if (timer->running)
- return 0;
- send_timer_event(timer->dp, SNDRV_SEQ_EVENT_CONTINUE, 0);
- timer->running = 1;
- return 0;
-}
-
-
-/*
- * change queue tempo
- */
-int
-snd_seq_oss_timer_tempo(struct seq_oss_timer *timer, int value)
-{
- if (value < MIN_OSS_TEMPO)
- value = MIN_OSS_TEMPO;
- else if (value > MAX_OSS_TEMPO)
- value = MAX_OSS_TEMPO;
- timer->oss_tempo = value;
- calc_alsa_tempo(timer);
- if (timer->running)
- send_timer_event(timer->dp, SNDRV_SEQ_EVENT_TEMPO, timer->tempo);
- return 0;
-}
-
-
-/*
- * ioctls
- */
-int
-snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __user *arg)
-{
- int value;
-
- if (cmd == SNDCTL_SEQ_CTRLRATE) {
- debug_printk(("ctrl rate\n"));
- /* if *arg == 0, just return the current rate */
- if (get_user(value, arg))
- return -EFAULT;
- if (value)
- return -EINVAL;
- value = ((timer->oss_tempo * timer->oss_timebase) + 30) / 60;
- return put_user(value, arg) ? -EFAULT : 0;
- }
-
- if (timer->dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH)
- return 0;
-
- switch (cmd) {
- case SNDCTL_TMR_START:
- debug_printk(("timer start\n"));
- return snd_seq_oss_timer_start(timer);
- case SNDCTL_TMR_STOP:
- debug_printk(("timer stop\n"));
- return snd_seq_oss_timer_stop(timer);
- case SNDCTL_TMR_CONTINUE:
- debug_printk(("timer continue\n"));
- return snd_seq_oss_timer_continue(timer);
- case SNDCTL_TMR_TEMPO:
- debug_printk(("timer tempo\n"));
- if (get_user(value, arg))
- return -EFAULT;
- return snd_seq_oss_timer_tempo(timer, value);
- case SNDCTL_TMR_TIMEBASE:
- debug_printk(("timer timebase\n"));
- if (get_user(value, arg))
- return -EFAULT;
- if (value < MIN_OSS_TIMEBASE)
- value = MIN_OSS_TIMEBASE;
- else if (value > MAX_OSS_TIMEBASE)
- value = MAX_OSS_TIMEBASE;
- timer->oss_timebase = value;
- calc_alsa_tempo(timer);
- return 0;
-
- case SNDCTL_TMR_METRONOME:
- case SNDCTL_TMR_SELECT:
- case SNDCTL_TMR_SOURCE:
- debug_printk(("timer XXX\n"));
- /* not supported */
- return 0;
- }
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.h
deleted file mode 100644
index b995bd68..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * OSS compatible sequencer driver
- * timer handling routines
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __SEQ_OSS_TIMER_H
-#define __SEQ_OSS_TIMER_H
-
-#include "seq_oss_device.h"
-
-/*
- * timer information definition
- */
-struct seq_oss_timer {
- struct seq_oss_devinfo *dp;
- reltime_t cur_tick;
- int realtime;
- int running;
- int tempo, ppq; /* ALSA queue */
- int oss_tempo, oss_timebase;
-};
-
-
-struct seq_oss_timer *snd_seq_oss_timer_new(struct seq_oss_devinfo *dp);
-void snd_seq_oss_timer_delete(struct seq_oss_timer *dp);
-
-int snd_seq_oss_timer_start(struct seq_oss_timer *timer);
-int snd_seq_oss_timer_stop(struct seq_oss_timer *timer);
-int snd_seq_oss_timer_continue(struct seq_oss_timer *timer);
-int snd_seq_oss_timer_tempo(struct seq_oss_timer *timer, int value);
-#define snd_seq_oss_timer_reset snd_seq_oss_timer_start
-
-int snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __user *arg);
-
-/*
- * get current processed time
- */
-static inline abstime_t
-snd_seq_oss_timer_cur_tick(struct seq_oss_timer *timer)
-{
- return timer->cur_tick;
-}
-
-
-/*
- * is realtime event?
- */
-static inline int
-snd_seq_oss_timer_is_realtime(struct seq_oss_timer *timer)
-{
- return timer->realtime;
-}
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.c
deleted file mode 100644
index d50338bb..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * OSS compatible sequencer driver
- *
- * seq_oss_writeq.c - write queue and sync
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "seq_oss_writeq.h"
-#include "seq_oss_event.h"
-#include "seq_oss_timer.h"
-#include <sound/seq_oss_legacy.h>
-#include "../seq_lock.h"
-#include "../seq_clientmgr.h"
-#include <linux/wait.h>
-#include <linux/slab.h>
-
-
-/*
- * create a write queue record
- */
-struct seq_oss_writeq *
-snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen)
-{
- struct seq_oss_writeq *q;
- struct snd_seq_client_pool pool;
-
- if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL)
- return NULL;
- q->dp = dp;
- q->maxlen = maxlen;
- spin_lock_init(&q->sync_lock);
- q->sync_event_put = 0;
- q->sync_time = 0;
- init_waitqueue_head(&q->sync_sleep);
-
- memset(&pool, 0, sizeof(pool));
- pool.client = dp->cseq;
- pool.output_pool = maxlen;
- pool.output_room = maxlen / 2;
-
- snd_seq_oss_control(dp, SNDRV_SEQ_IOCTL_SET_CLIENT_POOL, &pool);
-
- return q;
-}
-
-/*
- * delete the write queue
- */
-void
-snd_seq_oss_writeq_delete(struct seq_oss_writeq *q)
-{
- if (q) {
- snd_seq_oss_writeq_clear(q); /* to be sure */
- kfree(q);
- }
-}
-
-
-/*
- * reset the write queue
- */
-void
-snd_seq_oss_writeq_clear(struct seq_oss_writeq *q)
-{
- struct snd_seq_remove_events reset;
-
- memset(&reset, 0, sizeof(reset));
- reset.remove_mode = SNDRV_SEQ_REMOVE_OUTPUT; /* remove all */
- snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_REMOVE_EVENTS, &reset);
-
- /* wake up sleepers if any */
- snd_seq_oss_writeq_wakeup(q, 0);
-}
-
-/*
- * wait until the write buffer has enough room
- */
-int
-snd_seq_oss_writeq_sync(struct seq_oss_writeq *q)
-{
- struct seq_oss_devinfo *dp = q->dp;
- abstime_t time;
-
- time = snd_seq_oss_timer_cur_tick(dp->timer);
- if (q->sync_time >= time)
- return 0; /* already finished */
-
- if (! q->sync_event_put) {
- struct snd_seq_event ev;
- union evrec *rec;
-
- /* put echoback event */
- memset(&ev, 0, sizeof(ev));
- ev.flags = 0;
- ev.type = SNDRV_SEQ_EVENT_ECHO;
- ev.time.tick = time;
- /* echo back to itself */
- snd_seq_oss_fill_addr(dp, &ev, dp->addr.client, dp->addr.port);
- rec = (union evrec *)&ev.data;
- rec->t.code = SEQ_SYNCTIMER;
- rec->t.time = time;
- q->sync_event_put = 1;
- snd_seq_kernel_client_enqueue_blocking(dp->cseq, &ev, NULL, 0, 0);
- }
-
- wait_event_interruptible_timeout(q->sync_sleep, ! q->sync_event_put, HZ);
- if (signal_pending(current))
- /* interrupted - return 0 to finish sync */
- q->sync_event_put = 0;
- if (! q->sync_event_put || q->sync_time >= time)
- return 0;
- return 1;
-}
-
-/*
- * wake up sync - echo event was catched
- */
-void
-snd_seq_oss_writeq_wakeup(struct seq_oss_writeq *q, abstime_t time)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&q->sync_lock, flags);
- q->sync_time = time;
- q->sync_event_put = 0;
- if (waitqueue_active(&q->sync_sleep)) {
- wake_up(&q->sync_sleep);
- }
- spin_unlock_irqrestore(&q->sync_lock, flags);
-}
-
-
-/*
- * return the unused pool size
- */
-int
-snd_seq_oss_writeq_get_free_size(struct seq_oss_writeq *q)
-{
- struct snd_seq_client_pool pool;
- pool.client = q->dp->cseq;
- snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, &pool);
- return pool.output_free;
-}
-
-
-/*
- * set output threshold size from ioctl
- */
-void
-snd_seq_oss_writeq_set_output(struct seq_oss_writeq *q, int val)
-{
- struct snd_seq_client_pool pool;
- pool.client = q->dp->cseq;
- snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, &pool);
- pool.output_room = val;
- snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_SET_CLIENT_POOL, &pool);
-}
-
diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.h
deleted file mode 100644
index c469d296..00000000
--- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * OSS compatible sequencer driver
- * write priority queue
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __SEQ_OSS_WRITEQ_H
-#define __SEQ_OSS_WRITEQ_H
-
-#include "seq_oss_device.h"
-
-
-struct seq_oss_writeq {
- struct seq_oss_devinfo *dp;
- int maxlen;
- abstime_t sync_time;
- int sync_event_put;
- wait_queue_head_t sync_sleep;
- spinlock_t sync_lock;
-};
-
-
-/*
- * seq_oss_writeq.c
- */
-struct seq_oss_writeq *snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen);
-void snd_seq_oss_writeq_delete(struct seq_oss_writeq *q);
-void snd_seq_oss_writeq_clear(struct seq_oss_writeq *q);
-int snd_seq_oss_writeq_sync(struct seq_oss_writeq *q);
-void snd_seq_oss_writeq_wakeup(struct seq_oss_writeq *q, abstime_t time);
-int snd_seq_oss_writeq_get_free_size(struct seq_oss_writeq *q);
-void snd_seq_oss_writeq_set_output(struct seq_oss_writeq *q, int size);
-
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq.c b/ANDROID_3.4.5/sound/core/seq/seq.c
deleted file mode 100644
index 71211056..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * ALSA sequencer main module
- * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/initval.h>
-
-#include <sound/seq_kernel.h>
-#include "seq_clientmgr.h"
-#include "seq_memory.h"
-#include "seq_queue.h"
-#include "seq_lock.h"
-#include "seq_timer.h"
-#include "seq_system.h"
-#include "seq_info.h"
-#include <sound/minors.h>
-#include <sound/seq_device.h>
-
-#if defined(CONFIG_SND_SEQ_DUMMY_MODULE)
-int seq_client_load[15] = {[0] = SNDRV_SEQ_CLIENT_DUMMY, [1 ... 14] = -1};
-#else
-int seq_client_load[15] = {[0 ... 14] = -1};
-#endif
-int seq_default_timer_class = SNDRV_TIMER_CLASS_GLOBAL;
-int seq_default_timer_sclass = SNDRV_TIMER_SCLASS_NONE;
-int seq_default_timer_card = -1;
-int seq_default_timer_device =
-#ifdef CONFIG_SND_SEQ_HRTIMER_DEFAULT
- SNDRV_TIMER_GLOBAL_HRTIMER
-#elif defined(CONFIG_SND_SEQ_RTCTIMER_DEFAULT)
- SNDRV_TIMER_GLOBAL_RTC
-#else
- SNDRV_TIMER_GLOBAL_SYSTEM
-#endif
- ;
-int seq_default_timer_subdevice = 0;
-int seq_default_timer_resolution = 0; /* Hz */
-
-MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer.");
-MODULE_LICENSE("GPL");
-
-module_param_array(seq_client_load, int, NULL, 0444);
-MODULE_PARM_DESC(seq_client_load, "The numbers of global (system) clients to load through kmod.");
-module_param(seq_default_timer_class, int, 0644);
-MODULE_PARM_DESC(seq_default_timer_class, "The default timer class.");
-module_param(seq_default_timer_sclass, int, 0644);
-MODULE_PARM_DESC(seq_default_timer_sclass, "The default timer slave class.");
-module_param(seq_default_timer_card, int, 0644);
-MODULE_PARM_DESC(seq_default_timer_card, "The default timer card number.");
-module_param(seq_default_timer_device, int, 0644);
-MODULE_PARM_DESC(seq_default_timer_device, "The default timer device number.");
-module_param(seq_default_timer_subdevice, int, 0644);
-MODULE_PARM_DESC(seq_default_timer_subdevice, "The default timer subdevice number.");
-module_param(seq_default_timer_resolution, int, 0644);
-MODULE_PARM_DESC(seq_default_timer_resolution, "The default timer resolution in Hz.");
-
-MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_SEQUENCER);
-MODULE_ALIAS("devname:snd/seq");
-
-/*
- * INIT PART
- */
-
-static int __init alsa_seq_init(void)
-{
- int err;
-
- snd_seq_autoload_lock();
- if ((err = client_init_data()) < 0)
- goto error;
-
- /* init memory, room for selected events */
- if ((err = snd_sequencer_memory_init()) < 0)
- goto error;
-
- /* init event queues */
- if ((err = snd_seq_queues_init()) < 0)
- goto error;
-
- /* register sequencer device */
- if ((err = snd_sequencer_device_init()) < 0)
- goto error;
-
- /* register proc interface */
- if ((err = snd_seq_info_init()) < 0)
- goto error;
-
- /* register our internal client */
- if ((err = snd_seq_system_client_init()) < 0)
- goto error;
-
- error:
- snd_seq_autoload_unlock();
- return err;
-}
-
-static void __exit alsa_seq_exit(void)
-{
- /* unregister our internal client */
- snd_seq_system_client_done();
-
- /* unregister proc interface */
- snd_seq_info_done();
-
- /* delete timing queues */
- snd_seq_queues_delete();
-
- /* unregister sequencer device */
- snd_sequencer_device_done();
-
- /* release event memory */
- snd_sequencer_memory_done();
-}
-
-module_init(alsa_seq_init)
-module_exit(alsa_seq_exit)
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.c b/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.c
deleted file mode 100644
index 4dc6bae8..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.c
+++ /dev/null
@@ -1,2591 +0,0 @@
-/*
- * ALSA sequencer Client Manager
- * Copyright (c) 1998-2001 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@perex.cz>
- * Takashi Iwai <tiwai@suse.de>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <linux/kmod.h>
-
-#include <sound/seq_kernel.h>
-#include "seq_clientmgr.h"
-#include "seq_memory.h"
-#include "seq_queue.h"
-#include "seq_timer.h"
-#include "seq_info.h"
-#include "seq_system.h"
-#include <sound/seq_device.h>
-#ifdef CONFIG_COMPAT
-#include <linux/compat.h>
-#endif
-
-/* Client Manager
-
- * this module handles the connections of userland and kernel clients
- *
- */
-
-/*
- * There are four ranges of client numbers (last two shared):
- * 0..15: global clients
- * 16..127: statically allocated client numbers for cards 0..27
- * 128..191: dynamically allocated client numbers for cards 28..31
- * 128..191: dynamically allocated client numbers for applications
- */
-
-/* number of kernel non-card clients */
-#define SNDRV_SEQ_GLOBAL_CLIENTS 16
-/* clients per cards, for static clients */
-#define SNDRV_SEQ_CLIENTS_PER_CARD 4
-/* dynamically allocated client numbers (both kernel drivers and user space) */
-#define SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN 128
-
-#define SNDRV_SEQ_LFLG_INPUT 0x0001
-#define SNDRV_SEQ_LFLG_OUTPUT 0x0002
-#define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT)
-
-static DEFINE_SPINLOCK(clients_lock);
-static DEFINE_MUTEX(register_mutex);
-
-/*
- * client table
- */
-static char clienttablock[SNDRV_SEQ_MAX_CLIENTS];
-static struct snd_seq_client *clienttab[SNDRV_SEQ_MAX_CLIENTS];
-static struct snd_seq_usage client_usage;
-
-/*
- * prototypes
- */
-static int bounce_error_event(struct snd_seq_client *client,
- struct snd_seq_event *event,
- int err, int atomic, int hop);
-static int snd_seq_deliver_single_event(struct snd_seq_client *client,
- struct snd_seq_event *event,
- int filter, int atomic, int hop);
-
-/*
- */
-
-static inline mm_segment_t snd_enter_user(void)
-{
- mm_segment_t fs = get_fs();
- set_fs(get_ds());
- return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
- set_fs(fs);
-}
-
-/*
- */
-static inline unsigned short snd_seq_file_flags(struct file *file)
-{
- switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
- case FMODE_WRITE:
- return SNDRV_SEQ_LFLG_OUTPUT;
- case FMODE_READ:
- return SNDRV_SEQ_LFLG_INPUT;
- default:
- return SNDRV_SEQ_LFLG_OPEN;
- }
-}
-
-static inline int snd_seq_write_pool_allocated(struct snd_seq_client *client)
-{
- return snd_seq_total_cells(client->pool) > 0;
-}
-
-/* return pointer to client structure for specified id */
-static struct snd_seq_client *clientptr(int clientid)
-{
- if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) {
- snd_printd("Seq: oops. Trying to get pointer to client %d\n",
- clientid);
- return NULL;
- }
- return clienttab[clientid];
-}
-
-struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
-{
- unsigned long flags;
- struct snd_seq_client *client;
-
- if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) {
- snd_printd("Seq: oops. Trying to get pointer to client %d\n",
- clientid);
- return NULL;
- }
- spin_lock_irqsave(&clients_lock, flags);
- client = clientptr(clientid);
- if (client)
- goto __lock;
- if (clienttablock[clientid]) {
- spin_unlock_irqrestore(&clients_lock, flags);
- return NULL;
- }
- spin_unlock_irqrestore(&clients_lock, flags);
-#ifdef CONFIG_MODULES
- if (!in_interrupt()) {
- static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS];
- static char card_requested[SNDRV_CARDS];
- if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) {
- int idx;
-
- if (!client_requested[clientid]) {
- client_requested[clientid] = 1;
- for (idx = 0; idx < 15; idx++) {
- if (seq_client_load[idx] < 0)
- break;
- if (seq_client_load[idx] == clientid) {
- request_module("snd-seq-client-%i",
- clientid);
- break;
- }
- }
- }
- } else if (clientid < SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN) {
- int card = (clientid - SNDRV_SEQ_GLOBAL_CLIENTS) /
- SNDRV_SEQ_CLIENTS_PER_CARD;
- if (card < snd_ecards_limit) {
- if (! card_requested[card]) {
- card_requested[card] = 1;
- snd_request_card(card);
- }
- snd_seq_device_load_drivers();
- }
- }
- spin_lock_irqsave(&clients_lock, flags);
- client = clientptr(clientid);
- if (client)
- goto __lock;
- spin_unlock_irqrestore(&clients_lock, flags);
- }
-#endif
- return NULL;
-
- __lock:
- snd_use_lock_use(&client->use_lock);
- spin_unlock_irqrestore(&clients_lock, flags);
- return client;
-}
-
-static void usage_alloc(struct snd_seq_usage *res, int num)
-{
- res->cur += num;
- if (res->cur > res->peak)
- res->peak = res->cur;
-}
-
-static void usage_free(struct snd_seq_usage *res, int num)
-{
- res->cur -= num;
-}
-
-/* initialise data structures */
-int __init client_init_data(void)
-{
- /* zap out the client table */
- memset(&clienttablock, 0, sizeof(clienttablock));
- memset(&clienttab, 0, sizeof(clienttab));
- return 0;
-}
-
-
-static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
-{
- unsigned long flags;
- int c;
- struct snd_seq_client *client;
-
- /* init client data */
- client = kzalloc(sizeof(*client), GFP_KERNEL);
- if (client == NULL)
- return NULL;
- client->pool = snd_seq_pool_new(poolsize);
- if (client->pool == NULL) {
- kfree(client);
- return NULL;
- }
- client->type = NO_CLIENT;
- snd_use_lock_init(&client->use_lock);
- rwlock_init(&client->ports_lock);
- mutex_init(&client->ports_mutex);
- INIT_LIST_HEAD(&client->ports_list_head);
-
- /* find free slot in the client table */
- spin_lock_irqsave(&clients_lock, flags);
- if (client_index < 0) {
- for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN;
- c < SNDRV_SEQ_MAX_CLIENTS;
- c++) {
- if (clienttab[c] || clienttablock[c])
- continue;
- clienttab[client->number = c] = client;
- spin_unlock_irqrestore(&clients_lock, flags);
- return client;
- }
- } else {
- if (clienttab[client_index] == NULL && !clienttablock[client_index]) {
- clienttab[client->number = client_index] = client;
- spin_unlock_irqrestore(&clients_lock, flags);
- return client;
- }
- }
- spin_unlock_irqrestore(&clients_lock, flags);
- snd_seq_pool_delete(&client->pool);
- kfree(client);
- return NULL; /* no free slot found or busy, return failure code */
-}
-
-
-static int seq_free_client1(struct snd_seq_client *client)
-{
- unsigned long flags;
-
- if (!client)
- return 0;
- snd_seq_delete_all_ports(client);
- snd_seq_queue_client_leave(client->number);
- spin_lock_irqsave(&clients_lock, flags);
- clienttablock[client->number] = 1;
- clienttab[client->number] = NULL;
- spin_unlock_irqrestore(&clients_lock, flags);
- snd_use_lock_sync(&client->use_lock);
- snd_seq_queue_client_termination(client->number);
- if (client->pool)
- snd_seq_pool_delete(&client->pool);
- spin_lock_irqsave(&clients_lock, flags);
- clienttablock[client->number] = 0;
- spin_unlock_irqrestore(&clients_lock, flags);
- return 0;
-}
-
-
-static void seq_free_client(struct snd_seq_client * client)
-{
- mutex_lock(&register_mutex);
- switch (client->type) {
- case NO_CLIENT:
- snd_printk(KERN_WARNING "Seq: Trying to free unused client %d\n",
- client->number);
- break;
- case USER_CLIENT:
- case KERNEL_CLIENT:
- seq_free_client1(client);
- usage_free(&client_usage, 1);
- break;
-
- default:
- snd_printk(KERN_ERR "Seq: Trying to free client %d with undefined type = %d\n",
- client->number, client->type);
- }
- mutex_unlock(&register_mutex);
-
- snd_seq_system_client_ev_client_exit(client->number);
-}
-
-
-
-/* -------------------------------------------------------- */
-
-/* create a user client */
-static int snd_seq_open(struct inode *inode, struct file *file)
-{
- int c, mode; /* client id */
- struct snd_seq_client *client;
- struct snd_seq_user_client *user;
- int err;
-
- err = nonseekable_open(inode, file);
- if (err < 0)
- return err;
-
- if (mutex_lock_interruptible(&register_mutex))
- return -ERESTARTSYS;
- client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS);
- if (client == NULL) {
- mutex_unlock(&register_mutex);
- return -ENOMEM; /* failure code */
- }
-
- mode = snd_seq_file_flags(file);
- if (mode & SNDRV_SEQ_LFLG_INPUT)
- client->accept_input = 1;
- if (mode & SNDRV_SEQ_LFLG_OUTPUT)
- client->accept_output = 1;
-
- user = &client->data.user;
- user->fifo = NULL;
- user->fifo_pool_size = 0;
-
- if (mode & SNDRV_SEQ_LFLG_INPUT) {
- user->fifo_pool_size = SNDRV_SEQ_DEFAULT_CLIENT_EVENTS;
- user->fifo = snd_seq_fifo_new(user->fifo_pool_size);
- if (user->fifo == NULL) {
- seq_free_client1(client);
- kfree(client);
- mutex_unlock(&register_mutex);
- return -ENOMEM;
- }
- }
-
- usage_alloc(&client_usage, 1);
- client->type = USER_CLIENT;
- mutex_unlock(&register_mutex);
-
- c = client->number;
- file->private_data = client;
-
- /* fill client data */
- user->file = file;
- sprintf(client->name, "Client-%d", c);
-
- /* make others aware this new client */
- snd_seq_system_client_ev_client_start(c);
-
- return 0;
-}
-
-/* delete a user client */
-static int snd_seq_release(struct inode *inode, struct file *file)
-{
- struct snd_seq_client *client = file->private_data;
-
- if (client) {
- seq_free_client(client);
- if (client->data.user.fifo)
- snd_seq_fifo_delete(&client->data.user.fifo);
- kfree(client);
- }
-
- return 0;
-}
-
-
-/* handle client read() */
-/* possible error values:
- * -ENXIO invalid client or file open mode
- * -ENOSPC FIFO overflow (the flag is cleared after this error report)
- * -EINVAL no enough user-space buffer to write the whole event
- * -EFAULT seg. fault during copy to user space
- */
-static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
- loff_t *offset)
-{
- struct snd_seq_client *client = file->private_data;
- struct snd_seq_fifo *fifo;
- int err;
- long result = 0;
- struct snd_seq_event_cell *cell;
-
- if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT))
- return -ENXIO;
-
- if (!access_ok(VERIFY_WRITE, buf, count))
- return -EFAULT;
-
- /* check client structures are in place */
- if (snd_BUG_ON(!client))
- return -ENXIO;
-
- if (!client->accept_input || (fifo = client->data.user.fifo) == NULL)
- return -ENXIO;
-
- if (atomic_read(&fifo->overflow) > 0) {
- /* buffer overflow is detected */
- snd_seq_fifo_clear(fifo);
- /* return error code */
- return -ENOSPC;
- }
-
- cell = NULL;
- err = 0;
- snd_seq_fifo_lock(fifo);
-
- /* while data available in queue */
- while (count >= sizeof(struct snd_seq_event)) {
- int nonblock;
-
- nonblock = (file->f_flags & O_NONBLOCK) || result > 0;
- if ((err = snd_seq_fifo_cell_out(fifo, &cell, nonblock)) < 0) {
- break;
- }
- if (snd_seq_ev_is_variable(&cell->event)) {
- struct snd_seq_event tmpev;
- tmpev = cell->event;
- tmpev.data.ext.len &= ~SNDRV_SEQ_EXT_MASK;
- if (copy_to_user(buf, &tmpev, sizeof(struct snd_seq_event))) {
- err = -EFAULT;
- break;
- }
- count -= sizeof(struct snd_seq_event);
- buf += sizeof(struct snd_seq_event);
- err = snd_seq_expand_var_event(&cell->event, count,
- (char __force *)buf, 0,
- sizeof(struct snd_seq_event));
- if (err < 0)
- break;
- result += err;
- count -= err;
- buf += err;
- } else {
- if (copy_to_user(buf, &cell->event, sizeof(struct snd_seq_event))) {
- err = -EFAULT;
- break;
- }
- count -= sizeof(struct snd_seq_event);
- buf += sizeof(struct snd_seq_event);
- }
- snd_seq_cell_free(cell);
- cell = NULL; /* to be sure */
- result += sizeof(struct snd_seq_event);
- }
-
- if (err < 0) {
- if (cell)
- snd_seq_fifo_cell_putback(fifo, cell);
- if (err == -EAGAIN && result > 0)
- err = 0;
- }
- snd_seq_fifo_unlock(fifo);
-
- return (err < 0) ? err : result;
-}
-
-
-/*
- * check access permission to the port
- */
-static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags)
-{
- if ((port->capability & flags) != flags)
- return 0;
- return flags;
-}
-
-/*
- * check if the destination client is available, and return the pointer
- * if filter is non-zero, client filter bitmap is tested.
- */
-static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event,
- int filter)
-{
- struct snd_seq_client *dest;
-
- dest = snd_seq_client_use_ptr(event->dest.client);
- if (dest == NULL)
- return NULL;
- if (! dest->accept_input)
- goto __not_avail;
- if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) &&
- ! test_bit(event->type, dest->event_filter))
- goto __not_avail;
- if (filter && !(dest->filter & filter))
- goto __not_avail;
-
- return dest; /* ok - accessible */
-__not_avail:
- snd_seq_client_unlock(dest);
- return NULL;
-}
-
-
-/*
- * Return the error event.
- *
- * If the receiver client is a user client, the original event is
- * encapsulated in SNDRV_SEQ_EVENT_BOUNCE as variable length event. If
- * the original event is also variable length, the external data is
- * copied after the event record.
- * If the receiver client is a kernel client, the original event is
- * quoted in SNDRV_SEQ_EVENT_KERNEL_ERROR, since this requires no extra
- * kmalloc.
- */
-static int bounce_error_event(struct snd_seq_client *client,
- struct snd_seq_event *event,
- int err, int atomic, int hop)
-{
- struct snd_seq_event bounce_ev;
- int result;
-
- if (client == NULL ||
- ! (client->filter & SNDRV_SEQ_FILTER_BOUNCE) ||
- ! client->accept_input)
- return 0; /* ignored */
-
- /* set up quoted error */
- memset(&bounce_ev, 0, sizeof(bounce_ev));
- bounce_ev.type = SNDRV_SEQ_EVENT_KERNEL_ERROR;
- bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_FIXED;
- bounce_ev.queue = SNDRV_SEQ_QUEUE_DIRECT;
- bounce_ev.source.client = SNDRV_SEQ_CLIENT_SYSTEM;
- bounce_ev.source.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
- bounce_ev.dest.client = client->number;
- bounce_ev.dest.port = event->source.port;
- bounce_ev.data.quote.origin = event->dest;
- bounce_ev.data.quote.event = event;
- bounce_ev.data.quote.value = -err; /* use positive value */
- result = snd_seq_deliver_single_event(NULL, &bounce_ev, 0, atomic, hop + 1);
- if (result < 0) {
- client->event_lost++;
- return result;
- }
-
- return result;
-}
-
-
-/*
- * rewrite the time-stamp of the event record with the curren time
- * of the given queue.
- * return non-zero if updated.
- */
-static int update_timestamp_of_queue(struct snd_seq_event *event,
- int queue, int real_time)
-{
- struct snd_seq_queue *q;
-
- q = queueptr(queue);
- if (! q)
- return 0;
- event->queue = queue;
- event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK;
- if (real_time) {
- event->time.time = snd_seq_timer_get_cur_time(q->timer);
- event->flags |= SNDRV_SEQ_TIME_STAMP_REAL;
- } else {
- event->time.tick = snd_seq_timer_get_cur_tick(q->timer);
- event->flags |= SNDRV_SEQ_TIME_STAMP_TICK;
- }
- queuefree(q);
- return 1;
-}
-
-
-/*
- * deliver an event to the specified destination.
- * if filter is non-zero, client filter bitmap is tested.
- *
- * RETURN VALUE: 0 : if succeeded
- * <0 : error
- */
-static int snd_seq_deliver_single_event(struct snd_seq_client *client,
- struct snd_seq_event *event,
- int filter, int atomic, int hop)
-{
- struct snd_seq_client *dest = NULL;
- struct snd_seq_client_port *dest_port = NULL;
- int result = -ENOENT;
- int direct;
-
- direct = snd_seq_ev_is_direct(event);
-
- dest = get_event_dest_client(event, filter);
- if (dest == NULL)
- goto __skip;
- dest_port = snd_seq_port_use_ptr(dest, event->dest.port);
- if (dest_port == NULL)
- goto __skip;
-
- /* check permission */
- if (! check_port_perm(dest_port, SNDRV_SEQ_PORT_CAP_WRITE)) {
- result = -EPERM;
- goto __skip;
- }
-
- if (dest_port->timestamping)
- update_timestamp_of_queue(event, dest_port->time_queue,
- dest_port->time_real);
-
- switch (dest->type) {
- case USER_CLIENT:
- if (dest->data.user.fifo)
- result = snd_seq_fifo_event_in(dest->data.user.fifo, event);
- break;
-
- case KERNEL_CLIENT:
- if (dest_port->event_input == NULL)
- break;
- result = dest_port->event_input(event, direct,
- dest_port->private_data,
- atomic, hop);
- break;
- default:
- break;
- }
-
- __skip:
- if (dest_port)
- snd_seq_port_unlock(dest_port);
- if (dest)
- snd_seq_client_unlock(dest);
-
- if (result < 0 && !direct) {
- result = bounce_error_event(client, event, result, atomic, hop);
- }
- return result;
-}
-
-
-/*
- * send the event to all subscribers:
- */
-static int deliver_to_subscribers(struct snd_seq_client *client,
- struct snd_seq_event *event,
- int atomic, int hop)
-{
- struct snd_seq_subscribers *subs;
- int err = 0, num_ev = 0;
- struct snd_seq_event event_saved;
- struct snd_seq_client_port *src_port;
- struct snd_seq_port_subs_info *grp;
-
- src_port = snd_seq_port_use_ptr(client, event->source.port);
- if (src_port == NULL)
- return -EINVAL; /* invalid source port */
- /* save original event record */
- event_saved = *event;
- grp = &src_port->c_src;
-
- /* lock list */
- if (atomic)
- read_lock(&grp->list_lock);
- else
- down_read(&grp->list_mutex);
- list_for_each_entry(subs, &grp->list_head, src_list) {
- event->dest = subs->info.dest;
- if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
- /* convert time according to flag with subscription */
- update_timestamp_of_queue(event, subs->info.queue,
- subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL);
- err = snd_seq_deliver_single_event(client, event,
- 0, atomic, hop);
- if (err < 0)
- break;
- num_ev++;
- /* restore original event record */
- *event = event_saved;
- }
- if (atomic)
- read_unlock(&grp->list_lock);
- else
- up_read(&grp->list_mutex);
- *event = event_saved; /* restore */
- snd_seq_port_unlock(src_port);
- return (err < 0) ? err : num_ev;
-}
-
-
-#ifdef SUPPORT_BROADCAST
-/*
- * broadcast to all ports:
- */
-static int port_broadcast_event(struct snd_seq_client *client,
- struct snd_seq_event *event,
- int atomic, int hop)
-{
- int num_ev = 0, err = 0;
- struct snd_seq_client *dest_client;
- struct snd_seq_client_port *port;
-
- dest_client = get_event_dest_client(event, SNDRV_SEQ_FILTER_BROADCAST);
- if (dest_client == NULL)
- return 0; /* no matching destination */
-
- read_lock(&dest_client->ports_lock);
- list_for_each_entry(port, &dest_client->ports_list_head, list) {
- event->dest.port = port->addr.port;
- /* pass NULL as source client to avoid error bounce */
- err = snd_seq_deliver_single_event(NULL, event,
- SNDRV_SEQ_FILTER_BROADCAST,
- atomic, hop);
- if (err < 0)
- break;
- num_ev++;
- }
- read_unlock(&dest_client->ports_lock);
- snd_seq_client_unlock(dest_client);
- event->dest.port = SNDRV_SEQ_ADDRESS_BROADCAST; /* restore */
- return (err < 0) ? err : num_ev;
-}
-
-/*
- * send the event to all clients:
- * if destination port is also ADDRESS_BROADCAST, deliver to all ports.
- */
-static int broadcast_event(struct snd_seq_client *client,
- struct snd_seq_event *event, int atomic, int hop)
-{
- int err = 0, num_ev = 0;
- int dest;
- struct snd_seq_addr addr;
-
- addr = event->dest; /* save */
-
- for (dest = 0; dest < SNDRV_SEQ_MAX_CLIENTS; dest++) {
- /* don't send to itself */
- if (dest == client->number)
- continue;
- event->dest.client = dest;
- event->dest.port = addr.port;
- if (addr.port == SNDRV_SEQ_ADDRESS_BROADCAST)
- err = port_broadcast_event(client, event, atomic, hop);
- else
- /* pass NULL as source client to avoid error bounce */
- err = snd_seq_deliver_single_event(NULL, event,
- SNDRV_SEQ_FILTER_BROADCAST,
- atomic, hop);
- if (err < 0)
- break;
- num_ev += err;
- }
- event->dest = addr; /* restore */
- return (err < 0) ? err : num_ev;
-}
-
-
-/* multicast - not supported yet */
-static int multicast_event(struct snd_seq_client *client, struct snd_seq_event *event,
- int atomic, int hop)
-{
- snd_printd("seq: multicast not supported yet.\n");
- return 0; /* ignored */
-}
-#endif /* SUPPORT_BROADCAST */
-
-
-/* deliver an event to the destination port(s).
- * if the event is to subscribers or broadcast, the event is dispatched
- * to multiple targets.
- *
- * RETURN VALUE: n > 0 : the number of delivered events.
- * n == 0 : the event was not passed to any client.
- * n < 0 : error - event was not processed.
- */
-static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_event *event,
- int atomic, int hop)
-{
- int result;
-
- hop++;
- if (hop >= SNDRV_SEQ_MAX_HOPS) {
- snd_printd("too long delivery path (%d:%d->%d:%d)\n",
- event->source.client, event->source.port,
- event->dest.client, event->dest.port);
- return -EMLINK;
- }
-
- if (event->queue == SNDRV_SEQ_ADDRESS_SUBSCRIBERS ||
- event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS)
- result = deliver_to_subscribers(client, event, atomic, hop);
-#ifdef SUPPORT_BROADCAST
- else if (event->queue == SNDRV_SEQ_ADDRESS_BROADCAST ||
- event->dest.client == SNDRV_SEQ_ADDRESS_BROADCAST)
- result = broadcast_event(client, event, atomic, hop);
- else if (event->dest.client >= SNDRV_SEQ_MAX_CLIENTS)
- result = multicast_event(client, event, atomic, hop);
- else if (event->dest.port == SNDRV_SEQ_ADDRESS_BROADCAST)
- result = port_broadcast_event(client, event, atomic, hop);
-#endif
- else
- result = snd_seq_deliver_single_event(client, event, 0, atomic, hop);
-
- return result;
-}
-
-/*
- * dispatch an event cell:
- * This function is called only from queue check routines in timer
- * interrupts or after enqueued.
- * The event cell shall be released or re-queued in this function.
- *
- * RETURN VALUE: n > 0 : the number of delivered events.
- * n == 0 : the event was not passed to any client.
- * n < 0 : error - event was not processed.
- */
-int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
-{
- struct snd_seq_client *client;
- int result;
-
- if (snd_BUG_ON(!cell))
- return -EINVAL;
-
- client = snd_seq_client_use_ptr(cell->event.source.client);
- if (client == NULL) {
- snd_seq_cell_free(cell); /* release this cell */
- return -EINVAL;
- }
-
- if (cell->event.type == SNDRV_SEQ_EVENT_NOTE) {
- /* NOTE event:
- * the event cell is re-used as a NOTE-OFF event and
- * enqueued again.
- */
- struct snd_seq_event tmpev, *ev;
-
- /* reserve this event to enqueue note-off later */
- tmpev = cell->event;
- tmpev.type = SNDRV_SEQ_EVENT_NOTEON;
- result = snd_seq_deliver_event(client, &tmpev, atomic, hop);
-
- /*
- * This was originally a note event. We now re-use the
- * cell for the note-off event.
- */
-
- ev = &cell->event;
- ev->type = SNDRV_SEQ_EVENT_NOTEOFF;
- ev->flags |= SNDRV_SEQ_PRIORITY_HIGH;
-
- /* add the duration time */
- switch (ev->flags & SNDRV_SEQ_TIME_STAMP_MASK) {
- case SNDRV_SEQ_TIME_STAMP_TICK:
- ev->time.tick += ev->data.note.duration;
- break;
- case SNDRV_SEQ_TIME_STAMP_REAL:
- /* unit for duration is ms */
- ev->time.time.tv_nsec += 1000000 * (ev->data.note.duration % 1000);
- ev->time.time.tv_sec += ev->data.note.duration / 1000 +
- ev->time.time.tv_nsec / 1000000000;
- ev->time.time.tv_nsec %= 1000000000;
- break;
- }
- ev->data.note.velocity = ev->data.note.off_velocity;
-
- /* Now queue this cell as the note off event */
- if (snd_seq_enqueue_event(cell, atomic, hop) < 0)
- snd_seq_cell_free(cell); /* release this cell */
-
- } else {
- /* Normal events:
- * event cell is freed after processing the event
- */
-
- result = snd_seq_deliver_event(client, &cell->event, atomic, hop);
- snd_seq_cell_free(cell);
- }
-
- snd_seq_client_unlock(client);
- return result;
-}
-
-
-/* Allocate a cell from client pool and enqueue it to queue:
- * if pool is empty and blocking is TRUE, sleep until a new cell is
- * available.
- */
-static int snd_seq_client_enqueue_event(struct snd_seq_client *client,
- struct snd_seq_event *event,
- struct file *file, int blocking,
- int atomic, int hop)
-{
- struct snd_seq_event_cell *cell;
- int err;
-
- /* special queue values - force direct passing */
- if (event->queue == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) {
- event->dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- event->queue = SNDRV_SEQ_QUEUE_DIRECT;
- } else
-#ifdef SUPPORT_BROADCAST
- if (event->queue == SNDRV_SEQ_ADDRESS_BROADCAST) {
- event->dest.client = SNDRV_SEQ_ADDRESS_BROADCAST;
- event->queue = SNDRV_SEQ_QUEUE_DIRECT;
- }
-#endif
- if (event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) {
- /* check presence of source port */
- struct snd_seq_client_port *src_port = snd_seq_port_use_ptr(client, event->source.port);
- if (src_port == NULL)
- return -EINVAL;
- snd_seq_port_unlock(src_port);
- }
-
- /* direct event processing without enqueued */
- if (snd_seq_ev_is_direct(event)) {
- if (event->type == SNDRV_SEQ_EVENT_NOTE)
- return -EINVAL; /* this event must be enqueued! */
- return snd_seq_deliver_event(client, event, atomic, hop);
- }
-
- /* Not direct, normal queuing */
- if (snd_seq_queue_is_used(event->queue, client->number) <= 0)
- return -EINVAL; /* invalid queue */
- if (! snd_seq_write_pool_allocated(client))
- return -ENXIO; /* queue is not allocated */
-
- /* allocate an event cell */
- err = snd_seq_event_dup(client->pool, event, &cell, !blocking || atomic, file);
- if (err < 0)
- return err;
-
- /* we got a cell. enqueue it. */
- if ((err = snd_seq_enqueue_event(cell, atomic, hop)) < 0) {
- snd_seq_cell_free(cell);
- return err;
- }
-
- return 0;
-}
-
-
-/*
- * check validity of event type and data length.
- * return non-zero if invalid.
- */
-static int check_event_type_and_length(struct snd_seq_event *ev)
-{
- switch (snd_seq_ev_length_type(ev)) {
- case SNDRV_SEQ_EVENT_LENGTH_FIXED:
- if (snd_seq_ev_is_variable_type(ev))
- return -EINVAL;
- break;
- case SNDRV_SEQ_EVENT_LENGTH_VARIABLE:
- if (! snd_seq_ev_is_variable_type(ev) ||
- (ev->data.ext.len & ~SNDRV_SEQ_EXT_MASK) >= SNDRV_SEQ_MAX_EVENT_LEN)
- return -EINVAL;
- break;
- case SNDRV_SEQ_EVENT_LENGTH_VARUSR:
- if (! snd_seq_ev_is_direct(ev))
- return -EINVAL;
- break;
- }
- return 0;
-}
-
-
-/* handle write() */
-/* possible error values:
- * -ENXIO invalid client or file open mode
- * -ENOMEM malloc failed
- * -EFAULT seg. fault during copy from user space
- * -EINVAL invalid event
- * -EAGAIN no space in output pool
- * -EINTR interrupts while sleep
- * -EMLINK too many hops
- * others depends on return value from driver callback
- */
-static ssize_t snd_seq_write(struct file *file, const char __user *buf,
- size_t count, loff_t *offset)
-{
- struct snd_seq_client *client = file->private_data;
- int written = 0, len;
- int err = -EINVAL;
- struct snd_seq_event event;
-
- if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT))
- return -ENXIO;
-
- /* check client structures are in place */
- if (snd_BUG_ON(!client))
- return -ENXIO;
-
- if (!client->accept_output || client->pool == NULL)
- return -ENXIO;
-
- /* allocate the pool now if the pool is not allocated yet */
- if (client->pool->size > 0 && !snd_seq_write_pool_allocated(client)) {
- if (snd_seq_pool_init(client->pool) < 0)
- return -ENOMEM;
- }
-
- /* only process whole events */
- while (count >= sizeof(struct snd_seq_event)) {
- /* Read in the event header from the user */
- len = sizeof(event);
- if (copy_from_user(&event, buf, len)) {
- err = -EFAULT;
- break;
- }
- event.source.client = client->number; /* fill in client number */
- /* Check for extension data length */
- if (check_event_type_and_length(&event)) {
- err = -EINVAL;
- break;
- }
-
- /* check for special events */
- if (event.type == SNDRV_SEQ_EVENT_NONE)
- goto __skip_event;
- else if (snd_seq_ev_is_reserved(&event)) {
- err = -EINVAL;
- break;
- }
-
- if (snd_seq_ev_is_variable(&event)) {
- int extlen = event.data.ext.len & ~SNDRV_SEQ_EXT_MASK;
- if ((size_t)(extlen + len) > count) {
- /* back out, will get an error this time or next */
- err = -EINVAL;
- break;
- }
- /* set user space pointer */
- event.data.ext.len = extlen | SNDRV_SEQ_EXT_USRPTR;
- event.data.ext.ptr = (char __force *)buf
- + sizeof(struct snd_seq_event);
- len += extlen; /* increment data length */
- } else {
-#ifdef CONFIG_COMPAT
- if (client->convert32 && snd_seq_ev_is_varusr(&event)) {
- void *ptr = (void __force *)compat_ptr(event.data.raw32.d[1]);
- event.data.ext.ptr = ptr;
- }
-#endif
- }
-
- /* ok, enqueue it */
- err = snd_seq_client_enqueue_event(client, &event, file,
- !(file->f_flags & O_NONBLOCK),
- 0, 0);
- if (err < 0)
- break;
-
- __skip_event:
- /* Update pointers and counts */
- count -= len;
- buf += len;
- written += len;
- }
-
- return written ? written : err;
-}
-
-
-/*
- * handle polling
- */
-static unsigned int snd_seq_poll(struct file *file, poll_table * wait)
-{
- struct snd_seq_client *client = file->private_data;
- unsigned int mask = 0;
-
- /* check client structures are in place */
- if (snd_BUG_ON(!client))
- return -ENXIO;
-
- if ((snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT) &&
- client->data.user.fifo) {
-
- /* check if data is available in the outqueue */
- if (snd_seq_fifo_poll_wait(client->data.user.fifo, file, wait))
- mask |= POLLIN | POLLRDNORM;
- }
-
- if (snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT) {
-
- /* check if data is available in the pool */
- if (!snd_seq_write_pool_allocated(client) ||
- snd_seq_pool_poll_wait(client->pool, file, wait))
- mask |= POLLOUT | POLLWRNORM;
- }
-
- return mask;
-}
-
-
-/*-----------------------------------------------------*/
-
-
-/* SYSTEM_INFO ioctl() */
-static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user *arg)
-{
- struct snd_seq_system_info info;
-
- memset(&info, 0, sizeof(info));
- /* fill the info fields */
- info.queues = SNDRV_SEQ_MAX_QUEUES;
- info.clients = SNDRV_SEQ_MAX_CLIENTS;
- info.ports = 256; /* fixed limit */
- info.channels = 256; /* fixed limit */
- info.cur_clients = client_usage.cur;
- info.cur_queues = snd_seq_queue_get_cur_queues();
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-
-/* RUNNING_MODE ioctl() */
-static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void __user *arg)
-{
- struct snd_seq_running_info info;
- struct snd_seq_client *cptr;
- int err = 0;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- /* requested client number */
- cptr = snd_seq_client_use_ptr(info.client);
- if (cptr == NULL)
- return -ENOENT; /* don't change !!! */
-
-#ifdef SNDRV_BIG_ENDIAN
- if (! info.big_endian) {
- err = -EINVAL;
- goto __err;
- }
-#else
- if (info.big_endian) {
- err = -EINVAL;
- goto __err;
- }
-
-#endif
- if (info.cpu_mode > sizeof(long)) {
- err = -EINVAL;
- goto __err;
- }
- cptr->convert32 = (info.cpu_mode < sizeof(long));
- __err:
- snd_seq_client_unlock(cptr);
- return err;
-}
-
-/* CLIENT_INFO ioctl() */
-static void get_client_info(struct snd_seq_client *cptr,
- struct snd_seq_client_info *info)
-{
- info->client = cptr->number;
-
- /* fill the info fields */
- info->type = cptr->type;
- strcpy(info->name, cptr->name);
- info->filter = cptr->filter;
- info->event_lost = cptr->event_lost;
- memcpy(info->event_filter, cptr->event_filter, 32);
- info->num_ports = cptr->num_ports;
- memset(info->reserved, 0, sizeof(info->reserved));
-}
-
-static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_client *cptr;
- struct snd_seq_client_info client_info;
-
- if (copy_from_user(&client_info, arg, sizeof(client_info)))
- return -EFAULT;
-
- /* requested client number */
- cptr = snd_seq_client_use_ptr(client_info.client);
- if (cptr == NULL)
- return -ENOENT; /* don't change !!! */
-
- get_client_info(cptr, &client_info);
- snd_seq_client_unlock(cptr);
-
- if (copy_to_user(arg, &client_info, sizeof(client_info)))
- return -EFAULT;
- return 0;
-}
-
-
-/* CLIENT_INFO ioctl() */
-static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_client_info client_info;
-
- if (copy_from_user(&client_info, arg, sizeof(client_info)))
- return -EFAULT;
-
- /* it is not allowed to set the info fields for an another client */
- if (client->number != client_info.client)
- return -EPERM;
- /* also client type must be set now */
- if (client->type != client_info.type)
- return -EINVAL;
-
- /* fill the info fields */
- if (client_info.name[0])
- strlcpy(client->name, client_info.name, sizeof(client->name));
-
- client->filter = client_info.filter;
- client->event_lost = client_info.event_lost;
- memcpy(client->event_filter, client_info.event_filter, 32);
-
- return 0;
-}
-
-
-/*
- * CREATE PORT ioctl()
- */
-static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_client_port *port;
- struct snd_seq_port_info info;
- struct snd_seq_port_callback *callback;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- /* it is not allowed to create the port for an another client */
- if (info.addr.client != client->number)
- return -EPERM;
-
- port = snd_seq_create_port(client, (info.flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info.addr.port : -1);
- if (port == NULL)
- return -ENOMEM;
-
- if (client->type == USER_CLIENT && info.kernel) {
- snd_seq_delete_port(client, port->addr.port);
- return -EINVAL;
- }
- if (client->type == KERNEL_CLIENT) {
- if ((callback = info.kernel) != NULL) {
- if (callback->owner)
- port->owner = callback->owner;
- port->private_data = callback->private_data;
- port->private_free = callback->private_free;
- port->callback_all = callback->callback_all;
- port->event_input = callback->event_input;
- port->c_src.open = callback->subscribe;
- port->c_src.close = callback->unsubscribe;
- port->c_dest.open = callback->use;
- port->c_dest.close = callback->unuse;
- }
- }
-
- info.addr = port->addr;
-
- snd_seq_set_port_info(port, &info);
- snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
-
- return 0;
-}
-
-/*
- * DELETE PORT ioctl()
- */
-static int snd_seq_ioctl_delete_port(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_port_info info;
- int err;
-
- /* set passed parameters */
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- /* it is not allowed to remove the port for an another client */
- if (info.addr.client != client->number)
- return -EPERM;
-
- err = snd_seq_delete_port(client, info.addr.port);
- if (err >= 0)
- snd_seq_system_client_ev_port_exit(client->number, info.addr.port);
- return err;
-}
-
-
-/*
- * GET_PORT_INFO ioctl() (on any client)
- */
-static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_client *cptr;
- struct snd_seq_client_port *port;
- struct snd_seq_port_info info;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
- cptr = snd_seq_client_use_ptr(info.addr.client);
- if (cptr == NULL)
- return -ENXIO;
-
- port = snd_seq_port_use_ptr(cptr, info.addr.port);
- if (port == NULL) {
- snd_seq_client_unlock(cptr);
- return -ENOENT; /* don't change */
- }
-
- /* get port info */
- snd_seq_get_port_info(port, &info);
- snd_seq_port_unlock(port);
- snd_seq_client_unlock(cptr);
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-
-/*
- * SET_PORT_INFO ioctl() (only ports on this/own client)
- */
-static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_client_port *port;
- struct snd_seq_port_info info;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- if (info.addr.client != client->number) /* only set our own ports ! */
- return -EPERM;
- port = snd_seq_port_use_ptr(client, info.addr.port);
- if (port) {
- snd_seq_set_port_info(port, &info);
- snd_seq_port_unlock(port);
- }
- return 0;
-}
-
-
-/*
- * port subscription (connection)
- */
-#define PERM_RD (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ)
-#define PERM_WR (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE)
-
-static int check_subscription_permission(struct snd_seq_client *client,
- struct snd_seq_client_port *sport,
- struct snd_seq_client_port *dport,
- struct snd_seq_port_subscribe *subs)
-{
- if (client->number != subs->sender.client &&
- client->number != subs->dest.client) {
- /* connection by third client - check export permission */
- if (check_port_perm(sport, SNDRV_SEQ_PORT_CAP_NO_EXPORT))
- return -EPERM;
- if (check_port_perm(dport, SNDRV_SEQ_PORT_CAP_NO_EXPORT))
- return -EPERM;
- }
-
- /* check read permission */
- /* if sender or receiver is the subscribing client itself,
- * no permission check is necessary
- */
- if (client->number != subs->sender.client) {
- if (! check_port_perm(sport, PERM_RD))
- return -EPERM;
- }
- /* check write permission */
- if (client->number != subs->dest.client) {
- if (! check_port_perm(dport, PERM_WR))
- return -EPERM;
- }
- return 0;
-}
-
-/*
- * send an subscription notify event to user client:
- * client must be user client.
- */
-int snd_seq_client_notify_subscription(int client, int port,
- struct snd_seq_port_subscribe *info,
- int evtype)
-{
- struct snd_seq_event event;
-
- memset(&event, 0, sizeof(event));
- event.type = evtype;
- event.data.connect.dest = info->dest;
- event.data.connect.sender = info->sender;
-
- return snd_seq_system_notify(client, port, &event); /* non-atomic */
-}
-
-
-/*
- * add to port's subscription list IOCTL interface
- */
-static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
- void __user *arg)
-{
- int result = -EINVAL;
- struct snd_seq_client *receiver = NULL, *sender = NULL;
- struct snd_seq_client_port *sport = NULL, *dport = NULL;
- struct snd_seq_port_subscribe subs;
-
- if (copy_from_user(&subs, arg, sizeof(subs)))
- return -EFAULT;
-
- if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL)
- goto __end;
- if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL)
- goto __end;
- if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL)
- goto __end;
- if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL)
- goto __end;
-
- result = check_subscription_permission(client, sport, dport, &subs);
- if (result < 0)
- goto __end;
-
- /* connect them */
- result = snd_seq_port_connect(client, sender, sport, receiver, dport, &subs);
- if (! result) /* broadcast announce */
- snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,
- &subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);
- __end:
- if (sport)
- snd_seq_port_unlock(sport);
- if (dport)
- snd_seq_port_unlock(dport);
- if (sender)
- snd_seq_client_unlock(sender);
- if (receiver)
- snd_seq_client_unlock(receiver);
- return result;
-}
-
-
-/*
- * remove from port's subscription list
- */
-static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
- void __user *arg)
-{
- int result = -ENXIO;
- struct snd_seq_client *receiver = NULL, *sender = NULL;
- struct snd_seq_client_port *sport = NULL, *dport = NULL;
- struct snd_seq_port_subscribe subs;
-
- if (copy_from_user(&subs, arg, sizeof(subs)))
- return -EFAULT;
-
- if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL)
- goto __end;
- if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL)
- goto __end;
- if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL)
- goto __end;
- if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL)
- goto __end;
-
- result = check_subscription_permission(client, sport, dport, &subs);
- if (result < 0)
- goto __end;
-
- result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, &subs);
- if (! result) /* broadcast announce */
- snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,
- &subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);
- __end:
- if (sport)
- snd_seq_port_unlock(sport);
- if (dport)
- snd_seq_port_unlock(dport);
- if (sender)
- snd_seq_client_unlock(sender);
- if (receiver)
- snd_seq_client_unlock(receiver);
- return result;
-}
-
-
-/* CREATE_QUEUE ioctl() */
-static int snd_seq_ioctl_create_queue(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_queue_info info;
- int result;
- struct snd_seq_queue *q;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- result = snd_seq_queue_alloc(client->number, info.locked, info.flags);
- if (result < 0)
- return result;
-
- q = queueptr(result);
- if (q == NULL)
- return -EINVAL;
-
- info.queue = q->queue;
- info.locked = q->locked;
- info.owner = q->owner;
-
- /* set queue name */
- if (! info.name[0])
- snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue);
- strlcpy(q->name, info.name, sizeof(q->name));
- queuefree(q);
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
-
- return 0;
-}
-
-/* DELETE_QUEUE ioctl() */
-static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_queue_info info;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- return snd_seq_queue_delete(client->number, info.queue);
-}
-
-/* GET_QUEUE_INFO ioctl() */
-static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_queue_info info;
- struct snd_seq_queue *q;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- q = queueptr(info.queue);
- if (q == NULL)
- return -EINVAL;
-
- memset(&info, 0, sizeof(info));
- info.queue = q->queue;
- info.owner = q->owner;
- info.locked = q->locked;
- strlcpy(info.name, q->name, sizeof(info.name));
- queuefree(q);
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
-
- return 0;
-}
-
-/* SET_QUEUE_INFO ioctl() */
-static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_queue_info info;
- struct snd_seq_queue *q;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- if (info.owner != client->number)
- return -EINVAL;
-
- /* change owner/locked permission */
- if (snd_seq_queue_check_access(info.queue, client->number)) {
- if (snd_seq_queue_set_owner(info.queue, client->number, info.locked) < 0)
- return -EPERM;
- if (info.locked)
- snd_seq_queue_use(info.queue, client->number, 1);
- } else {
- return -EPERM;
- }
-
- q = queueptr(info.queue);
- if (! q)
- return -EINVAL;
- if (q->owner != client->number) {
- queuefree(q);
- return -EPERM;
- }
- strlcpy(q->name, info.name, sizeof(q->name));
- queuefree(q);
-
- return 0;
-}
-
-/* GET_NAMED_QUEUE ioctl() */
-static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, void __user *arg)
-{
- struct snd_seq_queue_info info;
- struct snd_seq_queue *q;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- q = snd_seq_queue_find_name(info.name);
- if (q == NULL)
- return -EINVAL;
- info.queue = q->queue;
- info.owner = q->owner;
- info.locked = q->locked;
- queuefree(q);
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
-
- return 0;
-}
-
-/* GET_QUEUE_STATUS ioctl() */
-static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_queue_status status;
- struct snd_seq_queue *queue;
- struct snd_seq_timer *tmr;
-
- if (copy_from_user(&status, arg, sizeof(status)))
- return -EFAULT;
-
- queue = queueptr(status.queue);
- if (queue == NULL)
- return -EINVAL;
- memset(&status, 0, sizeof(status));
- status.queue = queue->queue;
-
- tmr = queue->timer;
- status.events = queue->tickq->cells + queue->timeq->cells;
-
- status.time = snd_seq_timer_get_cur_time(tmr);
- status.tick = snd_seq_timer_get_cur_tick(tmr);
-
- status.running = tmr->running;
-
- status.flags = queue->flags;
- queuefree(queue);
-
- if (copy_to_user(arg, &status, sizeof(status)))
- return -EFAULT;
- return 0;
-}
-
-
-/* GET_QUEUE_TEMPO ioctl() */
-static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_queue_tempo tempo;
- struct snd_seq_queue *queue;
- struct snd_seq_timer *tmr;
-
- if (copy_from_user(&tempo, arg, sizeof(tempo)))
- return -EFAULT;
-
- queue = queueptr(tempo.queue);
- if (queue == NULL)
- return -EINVAL;
- memset(&tempo, 0, sizeof(tempo));
- tempo.queue = queue->queue;
-
- tmr = queue->timer;
-
- tempo.tempo = tmr->tempo;
- tempo.ppq = tmr->ppq;
- tempo.skew_value = tmr->skew;
- tempo.skew_base = tmr->skew_base;
- queuefree(queue);
-
- if (copy_to_user(arg, &tempo, sizeof(tempo)))
- return -EFAULT;
- return 0;
-}
-
-
-/* SET_QUEUE_TEMPO ioctl() */
-int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo)
-{
- if (!snd_seq_queue_check_access(tempo->queue, client))
- return -EPERM;
- return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
-}
-
-EXPORT_SYMBOL(snd_seq_set_queue_tempo);
-
-static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,
- void __user *arg)
-{
- int result;
- struct snd_seq_queue_tempo tempo;
-
- if (copy_from_user(&tempo, arg, sizeof(tempo)))
- return -EFAULT;
-
- result = snd_seq_set_queue_tempo(client->number, &tempo);
- return result < 0 ? result : 0;
-}
-
-
-/* GET_QUEUE_TIMER ioctl() */
-static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_queue_timer timer;
- struct snd_seq_queue *queue;
- struct snd_seq_timer *tmr;
-
- if (copy_from_user(&timer, arg, sizeof(timer)))
- return -EFAULT;
-
- queue = queueptr(timer.queue);
- if (queue == NULL)
- return -EINVAL;
-
- if (mutex_lock_interruptible(&queue->timer_mutex)) {
- queuefree(queue);
- return -ERESTARTSYS;
- }
- tmr = queue->timer;
- memset(&timer, 0, sizeof(timer));
- timer.queue = queue->queue;
-
- timer.type = tmr->type;
- if (tmr->type == SNDRV_SEQ_TIMER_ALSA) {
- timer.u.alsa.id = tmr->alsa_id;
- timer.u.alsa.resolution = tmr->preferred_resolution;
- }
- mutex_unlock(&queue->timer_mutex);
- queuefree(queue);
-
- if (copy_to_user(arg, &timer, sizeof(timer)))
- return -EFAULT;
- return 0;
-}
-
-
-/* SET_QUEUE_TIMER ioctl() */
-static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
- void __user *arg)
-{
- int result = 0;
- struct snd_seq_queue_timer timer;
-
- if (copy_from_user(&timer, arg, sizeof(timer)))
- return -EFAULT;
-
- if (timer.type != SNDRV_SEQ_TIMER_ALSA)
- return -EINVAL;
-
- if (snd_seq_queue_check_access(timer.queue, client->number)) {
- struct snd_seq_queue *q;
- struct snd_seq_timer *tmr;
-
- q = queueptr(timer.queue);
- if (q == NULL)
- return -ENXIO;
- if (mutex_lock_interruptible(&q->timer_mutex)) {
- queuefree(q);
- return -ERESTARTSYS;
- }
- tmr = q->timer;
- snd_seq_queue_timer_close(timer.queue);
- tmr->type = timer.type;
- if (tmr->type == SNDRV_SEQ_TIMER_ALSA) {
- tmr->alsa_id = timer.u.alsa.id;
- tmr->preferred_resolution = timer.u.alsa.resolution;
- }
- result = snd_seq_queue_timer_open(timer.queue);
- mutex_unlock(&q->timer_mutex);
- queuefree(q);
- } else {
- return -EPERM;
- }
-
- return result;
-}
-
-
-/* GET_QUEUE_CLIENT ioctl() */
-static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_queue_client info;
- int used;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- used = snd_seq_queue_is_used(info.queue, client->number);
- if (used < 0)
- return -EINVAL;
- info.used = used;
- info.client = client->number;
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-
-/* SET_QUEUE_CLIENT ioctl() */
-static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client,
- void __user *arg)
-{
- int err;
- struct snd_seq_queue_client info;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- if (info.used >= 0) {
- err = snd_seq_queue_use(info.queue, client->number, info.used);
- if (err < 0)
- return err;
- }
-
- return snd_seq_ioctl_get_queue_client(client, arg);
-}
-
-
-/* GET_CLIENT_POOL ioctl() */
-static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_client_pool info;
- struct snd_seq_client *cptr;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- cptr = snd_seq_client_use_ptr(info.client);
- if (cptr == NULL)
- return -ENOENT;
- memset(&info, 0, sizeof(info));
- info.output_pool = cptr->pool->size;
- info.output_room = cptr->pool->room;
- info.output_free = info.output_pool;
- info.output_free = snd_seq_unused_cells(cptr->pool);
- if (cptr->type == USER_CLIENT) {
- info.input_pool = cptr->data.user.fifo_pool_size;
- info.input_free = info.input_pool;
- if (cptr->data.user.fifo)
- info.input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool);
- } else {
- info.input_pool = 0;
- info.input_free = 0;
- }
- snd_seq_client_unlock(cptr);
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-/* SET_CLIENT_POOL ioctl() */
-static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_client_pool info;
- int rc;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- if (client->number != info.client)
- return -EINVAL; /* can't change other clients */
-
- if (info.output_pool >= 1 && info.output_pool <= SNDRV_SEQ_MAX_EVENTS &&
- (! snd_seq_write_pool_allocated(client) ||
- info.output_pool != client->pool->size)) {
- if (snd_seq_write_pool_allocated(client)) {
- /* remove all existing cells */
- snd_seq_queue_client_leave_cells(client->number);
- snd_seq_pool_done(client->pool);
- }
- client->pool->size = info.output_pool;
- rc = snd_seq_pool_init(client->pool);
- if (rc < 0)
- return rc;
- }
- if (client->type == USER_CLIENT && client->data.user.fifo != NULL &&
- info.input_pool >= 1 &&
- info.input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS &&
- info.input_pool != client->data.user.fifo_pool_size) {
- /* change pool size */
- rc = snd_seq_fifo_resize(client->data.user.fifo, info.input_pool);
- if (rc < 0)
- return rc;
- client->data.user.fifo_pool_size = info.input_pool;
- }
- if (info.output_room >= 1 &&
- info.output_room <= client->pool->size) {
- client->pool->room = info.output_room;
- }
-
- return snd_seq_ioctl_get_client_pool(client, arg);
-}
-
-
-/* REMOVE_EVENTS ioctl() */
-static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_remove_events info;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- /*
- * Input mostly not implemented XXX.
- */
- if (info.remove_mode & SNDRV_SEQ_REMOVE_INPUT) {
- /*
- * No restrictions so for a user client we can clear
- * the whole fifo
- */
- if (client->type == USER_CLIENT)
- snd_seq_fifo_clear(client->data.user.fifo);
- }
-
- if (info.remove_mode & SNDRV_SEQ_REMOVE_OUTPUT)
- snd_seq_queue_remove_cells(client->number, &info);
-
- return 0;
-}
-
-
-/*
- * get subscription info
- */
-static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
- void __user *arg)
-{
- int result;
- struct snd_seq_client *sender = NULL;
- struct snd_seq_client_port *sport = NULL;
- struct snd_seq_port_subscribe subs;
- struct snd_seq_subscribers *p;
-
- if (copy_from_user(&subs, arg, sizeof(subs)))
- return -EFAULT;
-
- result = -EINVAL;
- if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL)
- goto __end;
- if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL)
- goto __end;
- p = snd_seq_port_get_subscription(&sport->c_src, &subs.dest);
- if (p) {
- result = 0;
- subs = p->info;
- } else
- result = -ENOENT;
-
- __end:
- if (sport)
- snd_seq_port_unlock(sport);
- if (sender)
- snd_seq_client_unlock(sender);
- if (result >= 0) {
- if (copy_to_user(arg, &subs, sizeof(subs)))
- return -EFAULT;
- }
- return result;
-}
-
-
-/*
- * get subscription info - check only its presence
- */
-static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
- void __user *arg)
-{
- int result = -ENXIO;
- struct snd_seq_client *cptr = NULL;
- struct snd_seq_client_port *port = NULL;
- struct snd_seq_query_subs subs;
- struct snd_seq_port_subs_info *group;
- struct list_head *p;
- int i;
-
- if (copy_from_user(&subs, arg, sizeof(subs)))
- return -EFAULT;
-
- if ((cptr = snd_seq_client_use_ptr(subs.root.client)) == NULL)
- goto __end;
- if ((port = snd_seq_port_use_ptr(cptr, subs.root.port)) == NULL)
- goto __end;
-
- switch (subs.type) {
- case SNDRV_SEQ_QUERY_SUBS_READ:
- group = &port->c_src;
- break;
- case SNDRV_SEQ_QUERY_SUBS_WRITE:
- group = &port->c_dest;
- break;
- default:
- goto __end;
- }
-
- down_read(&group->list_mutex);
- /* search for the subscriber */
- subs.num_subs = group->count;
- i = 0;
- result = -ENOENT;
- list_for_each(p, &group->list_head) {
- if (i++ == subs.index) {
- /* found! */
- struct snd_seq_subscribers *s;
- if (subs.type == SNDRV_SEQ_QUERY_SUBS_READ) {
- s = list_entry(p, struct snd_seq_subscribers, src_list);
- subs.addr = s->info.dest;
- } else {
- s = list_entry(p, struct snd_seq_subscribers, dest_list);
- subs.addr = s->info.sender;
- }
- subs.flags = s->info.flags;
- subs.queue = s->info.queue;
- result = 0;
- break;
- }
- }
- up_read(&group->list_mutex);
-
- __end:
- if (port)
- snd_seq_port_unlock(port);
- if (cptr)
- snd_seq_client_unlock(cptr);
- if (result >= 0) {
- if (copy_to_user(arg, &subs, sizeof(subs)))
- return -EFAULT;
- }
- return result;
-}
-
-
-/*
- * query next client
- */
-static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_client *cptr = NULL;
- struct snd_seq_client_info info;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
-
- /* search for next client */
- info.client++;
- if (info.client < 0)
- info.client = 0;
- for (; info.client < SNDRV_SEQ_MAX_CLIENTS; info.client++) {
- cptr = snd_seq_client_use_ptr(info.client);
- if (cptr)
- break; /* found */
- }
- if (cptr == NULL)
- return -ENOENT;
-
- get_client_info(cptr, &info);
- snd_seq_client_unlock(cptr);
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-/*
- * query next port
- */
-static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
- void __user *arg)
-{
- struct snd_seq_client *cptr;
- struct snd_seq_client_port *port = NULL;
- struct snd_seq_port_info info;
-
- if (copy_from_user(&info, arg, sizeof(info)))
- return -EFAULT;
- cptr = snd_seq_client_use_ptr(info.addr.client);
- if (cptr == NULL)
- return -ENXIO;
-
- /* search for next port */
- info.addr.port++;
- port = snd_seq_port_query_nearest(cptr, &info);
- if (port == NULL) {
- snd_seq_client_unlock(cptr);
- return -ENOENT;
- }
-
- /* get port info */
- info.addr = port->addr;
- snd_seq_get_port_info(port, &info);
- snd_seq_port_unlock(port);
- snd_seq_client_unlock(cptr);
-
- if (copy_to_user(arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
-}
-
-/* -------------------------------------------------------- */
-
-static struct seq_ioctl_table {
- unsigned int cmd;
- int (*func)(struct snd_seq_client *client, void __user * arg);
-} ioctl_tables[] = {
- { SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info },
- { SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode },
- { SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, snd_seq_ioctl_get_client_info },
- { SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, snd_seq_ioctl_set_client_info },
- { SNDRV_SEQ_IOCTL_CREATE_PORT, snd_seq_ioctl_create_port },
- { SNDRV_SEQ_IOCTL_DELETE_PORT, snd_seq_ioctl_delete_port },
- { SNDRV_SEQ_IOCTL_GET_PORT_INFO, snd_seq_ioctl_get_port_info },
- { SNDRV_SEQ_IOCTL_SET_PORT_INFO, snd_seq_ioctl_set_port_info },
- { SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, snd_seq_ioctl_subscribe_port },
- { SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, snd_seq_ioctl_unsubscribe_port },
- { SNDRV_SEQ_IOCTL_CREATE_QUEUE, snd_seq_ioctl_create_queue },
- { SNDRV_SEQ_IOCTL_DELETE_QUEUE, snd_seq_ioctl_delete_queue },
- { SNDRV_SEQ_IOCTL_GET_QUEUE_INFO, snd_seq_ioctl_get_queue_info },
- { SNDRV_SEQ_IOCTL_SET_QUEUE_INFO, snd_seq_ioctl_set_queue_info },
- { SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE, snd_seq_ioctl_get_named_queue },
- { SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS, snd_seq_ioctl_get_queue_status },
- { SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO, snd_seq_ioctl_get_queue_tempo },
- { SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, snd_seq_ioctl_set_queue_tempo },
- { SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER, snd_seq_ioctl_get_queue_timer },
- { SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER, snd_seq_ioctl_set_queue_timer },
- { SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT, snd_seq_ioctl_get_queue_client },
- { SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT, snd_seq_ioctl_set_queue_client },
- { SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, snd_seq_ioctl_get_client_pool },
- { SNDRV_SEQ_IOCTL_SET_CLIENT_POOL, snd_seq_ioctl_set_client_pool },
- { SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION, snd_seq_ioctl_get_subscription },
- { SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, snd_seq_ioctl_query_next_client },
- { SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, snd_seq_ioctl_query_next_port },
- { SNDRV_SEQ_IOCTL_REMOVE_EVENTS, snd_seq_ioctl_remove_events },
- { SNDRV_SEQ_IOCTL_QUERY_SUBS, snd_seq_ioctl_query_subs },
- { 0, NULL },
-};
-
-static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd,
- void __user *arg)
-{
- struct seq_ioctl_table *p;
-
- switch (cmd) {
- case SNDRV_SEQ_IOCTL_PVERSION:
- /* return sequencer version number */
- return put_user(SNDRV_SEQ_VERSION, (int __user *)arg) ? -EFAULT : 0;
- case SNDRV_SEQ_IOCTL_CLIENT_ID:
- /* return the id of this client */
- return put_user(client->number, (int __user *)arg) ? -EFAULT : 0;
- }
-
- if (! arg)
- return -EFAULT;
- for (p = ioctl_tables; p->cmd; p++) {
- if (p->cmd == cmd)
- return p->func(client, arg);
- }
- snd_printd("seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n",
- cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
- return -ENOTTY;
-}
-
-
-static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct snd_seq_client *client = file->private_data;
-
- if (snd_BUG_ON(!client))
- return -ENXIO;
-
- return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
-}
-
-#ifdef CONFIG_COMPAT
-#include "seq_compat.c"
-#else
-#define snd_seq_ioctl_compat NULL
-#endif
-
-/* -------------------------------------------------------- */
-
-
-/* exported to kernel modules */
-int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
- const char *name_fmt, ...)
-{
- struct snd_seq_client *client;
- va_list args;
-
- if (snd_BUG_ON(in_interrupt()))
- return -EBUSY;
-
- if (card && client_index >= SNDRV_SEQ_CLIENTS_PER_CARD)
- return -EINVAL;
- if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS)
- return -EINVAL;
-
- if (mutex_lock_interruptible(&register_mutex))
- return -ERESTARTSYS;
-
- if (card) {
- client_index += SNDRV_SEQ_GLOBAL_CLIENTS
- + card->number * SNDRV_SEQ_CLIENTS_PER_CARD;
- if (client_index >= SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN)
- client_index = -1;
- }
-
- /* empty write queue as default */
- client = seq_create_client1(client_index, 0);
- if (client == NULL) {
- mutex_unlock(&register_mutex);
- return -EBUSY; /* failure code */
- }
- usage_alloc(&client_usage, 1);
-
- client->accept_input = 1;
- client->accept_output = 1;
-
- va_start(args, name_fmt);
- vsnprintf(client->name, sizeof(client->name), name_fmt, args);
- va_end(args);
-
- client->type = KERNEL_CLIENT;
- mutex_unlock(&register_mutex);
-
- /* make others aware this new client */
- snd_seq_system_client_ev_client_start(client->number);
-
- /* return client number to caller */
- return client->number;
-}
-
-EXPORT_SYMBOL(snd_seq_create_kernel_client);
-
-/* exported to kernel modules */
-int snd_seq_delete_kernel_client(int client)
-{
- struct snd_seq_client *ptr;
-
- if (snd_BUG_ON(in_interrupt()))
- return -EBUSY;
-
- ptr = clientptr(client);
- if (ptr == NULL)
- return -EINVAL;
-
- seq_free_client(ptr);
- kfree(ptr);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_seq_delete_kernel_client);
-
-/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue
- * and snd_seq_kernel_client_enqueue_blocking
- */
-static int kernel_client_enqueue(int client, struct snd_seq_event *ev,
- struct file *file, int blocking,
- int atomic, int hop)
-{
- struct snd_seq_client *cptr;
- int result;
-
- if (snd_BUG_ON(!ev))
- return -EINVAL;
-
- if (ev->type == SNDRV_SEQ_EVENT_NONE)
- return 0; /* ignore this */
- if (ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
- return -EINVAL; /* quoted events can't be enqueued */
-
- /* fill in client number */
- ev->source.client = client;
-
- if (check_event_type_and_length(ev))
- return -EINVAL;
-
- cptr = snd_seq_client_use_ptr(client);
- if (cptr == NULL)
- return -EINVAL;
-
- if (! cptr->accept_output)
- result = -EPERM;
- else /* send it */
- result = snd_seq_client_enqueue_event(cptr, ev, file, blocking, atomic, hop);
-
- snd_seq_client_unlock(cptr);
- return result;
-}
-
-/*
- * exported, called by kernel clients to enqueue events (w/o blocking)
- *
- * RETURN VALUE: zero if succeed, negative if error
- */
-int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev,
- int atomic, int hop)
-{
- return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop);
-}
-
-EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
-
-/*
- * exported, called by kernel clients to enqueue events (with blocking)
- *
- * RETURN VALUE: zero if succeed, negative if error
- */
-int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev,
- struct file *file,
- int atomic, int hop)
-{
- return kernel_client_enqueue(client, ev, file, 1, atomic, hop);
-}
-
-EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
-
-/*
- * exported, called by kernel clients to dispatch events directly to other
- * clients, bypassing the queues. Event time-stamp will be updated.
- *
- * RETURN VALUE: negative = delivery failed,
- * zero, or positive: the number of delivered events
- */
-int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
- int atomic, int hop)
-{
- struct snd_seq_client *cptr;
- int result;
-
- if (snd_BUG_ON(!ev))
- return -EINVAL;
-
- /* fill in client number */
- ev->queue = SNDRV_SEQ_QUEUE_DIRECT;
- ev->source.client = client;
-
- if (check_event_type_and_length(ev))
- return -EINVAL;
-
- cptr = snd_seq_client_use_ptr(client);
- if (cptr == NULL)
- return -EINVAL;
-
- if (!cptr->accept_output)
- result = -EPERM;
- else
- result = snd_seq_deliver_event(cptr, ev, atomic, hop);
-
- snd_seq_client_unlock(cptr);
- return result;
-}
-
-EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
-
-/*
- * exported, called by kernel clients to perform same functions as with
- * userland ioctl()
- */
-int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
-{
- struct snd_seq_client *client;
- mm_segment_t fs;
- int result;
-
- client = clientptr(clientid);
- if (client == NULL)
- return -ENXIO;
- fs = snd_enter_user();
- result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg);
- snd_leave_user(fs);
- return result;
-}
-
-EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
-
-/* exported (for OSS emulator) */
-int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait)
-{
- struct snd_seq_client *client;
-
- client = clientptr(clientid);
- if (client == NULL)
- return -ENXIO;
-
- if (! snd_seq_write_pool_allocated(client))
- return 1;
- if (snd_seq_pool_poll_wait(client->pool, file, wait))
- return 1;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
-
-/*---------------------------------------------------------------------------*/
-
-#ifdef CONFIG_PROC_FS
-/*
- * /proc interface
- */
-static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer,
- struct snd_seq_port_subs_info *group,
- int is_src, char *msg)
-{
- struct list_head *p;
- struct snd_seq_subscribers *s;
- int count = 0;
-
- down_read(&group->list_mutex);
- if (list_empty(&group->list_head)) {
- up_read(&group->list_mutex);
- return;
- }
- snd_iprintf(buffer, msg);
- list_for_each(p, &group->list_head) {
- if (is_src)
- s = list_entry(p, struct snd_seq_subscribers, src_list);
- else
- s = list_entry(p, struct snd_seq_subscribers, dest_list);
- if (count++)
- snd_iprintf(buffer, ", ");
- snd_iprintf(buffer, "%d:%d",
- is_src ? s->info.dest.client : s->info.sender.client,
- is_src ? s->info.dest.port : s->info.sender.port);
- if (s->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
- snd_iprintf(buffer, "[%c:%d]", ((s->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL) ? 'r' : 't'), s->info.queue);
- if (group->exclusive)
- snd_iprintf(buffer, "[ex]");
- }
- up_read(&group->list_mutex);
- snd_iprintf(buffer, "\n");
-}
-
-#define FLAG_PERM_RD(perm) ((perm) & SNDRV_SEQ_PORT_CAP_READ ? ((perm) & SNDRV_SEQ_PORT_CAP_SUBS_READ ? 'R' : 'r') : '-')
-#define FLAG_PERM_WR(perm) ((perm) & SNDRV_SEQ_PORT_CAP_WRITE ? ((perm) & SNDRV_SEQ_PORT_CAP_SUBS_WRITE ? 'W' : 'w') : '-')
-#define FLAG_PERM_EX(perm) ((perm) & SNDRV_SEQ_PORT_CAP_NO_EXPORT ? '-' : 'e')
-
-#define FLAG_PERM_DUPLEX(perm) ((perm) & SNDRV_SEQ_PORT_CAP_DUPLEX ? 'X' : '-')
-
-static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
- struct snd_seq_client *client)
-{
- struct snd_seq_client_port *p;
-
- mutex_lock(&client->ports_mutex);
- list_for_each_entry(p, &client->ports_list_head, list) {
- snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c)\n",
- p->addr.port, p->name,
- FLAG_PERM_RD(p->capability),
- FLAG_PERM_WR(p->capability),
- FLAG_PERM_EX(p->capability),
- FLAG_PERM_DUPLEX(p->capability));
- snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: ");
- snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: ");
- }
- mutex_unlock(&client->ports_mutex);
-}
-
-
-/* exported to seq_info.c */
-void snd_seq_info_clients_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- int c;
- struct snd_seq_client *client;
-
- snd_iprintf(buffer, "Client info\n");
- snd_iprintf(buffer, " cur clients : %d\n", client_usage.cur);
- snd_iprintf(buffer, " peak clients : %d\n", client_usage.peak);
- snd_iprintf(buffer, " max clients : %d\n", SNDRV_SEQ_MAX_CLIENTS);
- snd_iprintf(buffer, "\n");
-
- /* list the client table */
- for (c = 0; c < SNDRV_SEQ_MAX_CLIENTS; c++) {
- client = snd_seq_client_use_ptr(c);
- if (client == NULL)
- continue;
- if (client->type == NO_CLIENT) {
- snd_seq_client_unlock(client);
- continue;
- }
-
- snd_iprintf(buffer, "Client %3d : \"%s\" [%s]\n",
- c, client->name,
- client->type == USER_CLIENT ? "User" : "Kernel");
- snd_seq_info_dump_ports(buffer, client);
- if (snd_seq_write_pool_allocated(client)) {
- snd_iprintf(buffer, " Output pool :\n");
- snd_seq_info_pool(buffer, client->pool, " ");
- }
- if (client->type == USER_CLIENT && client->data.user.fifo &&
- client->data.user.fifo->pool) {
- snd_iprintf(buffer, " Input pool :\n");
- snd_seq_info_pool(buffer, client->data.user.fifo->pool, " ");
- }
- snd_seq_client_unlock(client);
- }
-}
-#endif /* CONFIG_PROC_FS */
-
-/*---------------------------------------------------------------------------*/
-
-
-/*
- * REGISTRATION PART
- */
-
-static const struct file_operations snd_seq_f_ops =
-{
- .owner = THIS_MODULE,
- .read = snd_seq_read,
- .write = snd_seq_write,
- .open = snd_seq_open,
- .release = snd_seq_release,
- .llseek = no_llseek,
- .poll = snd_seq_poll,
- .unlocked_ioctl = snd_seq_ioctl,
- .compat_ioctl = snd_seq_ioctl_compat,
-};
-
-/*
- * register sequencer device
- */
-int __init snd_sequencer_device_init(void)
-{
- int err;
-
- if (mutex_lock_interruptible(&register_mutex))
- return -ERESTARTSYS;
-
- if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
- &snd_seq_f_ops, NULL, "seq")) < 0) {
- mutex_unlock(&register_mutex);
- return err;
- }
-
- mutex_unlock(&register_mutex);
-
- return 0;
-}
-
-
-
-/*
- * unregister sequencer device
- */
-void __exit snd_sequencer_device_done(void)
-{
- snd_unregister_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0);
-}
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.h b/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.h
deleted file mode 100644
index 20f0a725..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * ALSA sequencer Client Manager
- * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __SND_SEQ_CLIENTMGR_H
-#define __SND_SEQ_CLIENTMGR_H
-
-#include <sound/seq_kernel.h>
-#include <linux/bitops.h>
-#include "seq_fifo.h"
-#include "seq_ports.h"
-#include "seq_lock.h"
-
-
-/* client manager */
-
-struct snd_seq_user_client {
- struct file *file; /* file struct of client */
- /* ... */
-
- /* fifo */
- struct snd_seq_fifo *fifo; /* queue for incoming events */
- int fifo_pool_size;
-};
-
-struct snd_seq_kernel_client {
- /* ... */
-};
-
-
-struct snd_seq_client {
- snd_seq_client_type_t type;
- unsigned int accept_input: 1,
- accept_output: 1;
- char name[64]; /* client name */
- int number; /* client number */
- unsigned int filter; /* filter flags */
- DECLARE_BITMAP(event_filter, 256);
- snd_use_lock_t use_lock;
- int event_lost;
- /* ports */
- int num_ports; /* number of ports */
- struct list_head ports_list_head;
- rwlock_t ports_lock;
- struct mutex ports_mutex;
- int convert32; /* convert 32->64bit */
-
- /* output pool */
- struct snd_seq_pool *pool; /* memory pool for this client */
-
- union {
- struct snd_seq_user_client user;
- struct snd_seq_kernel_client kernel;
- } data;
-};
-
-/* usage statistics */
-struct snd_seq_usage {
- int cur;
- int peak;
-};
-
-
-int client_init_data(void);
-int snd_sequencer_device_init(void);
-void snd_sequencer_device_done(void);
-
-/* get locked pointer to client */
-struct snd_seq_client *snd_seq_client_use_ptr(int clientid);
-
-/* unlock pointer to client */
-#define snd_seq_client_unlock(client) snd_use_lock_free(&(client)->use_lock)
-
-/* dispatch event to client(s) */
-int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop);
-
-/* exported to other modules */
-int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev, int atomic, int hop);
-int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev,
- struct file *file, int atomic, int hop);
-int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait);
-int snd_seq_client_notify_subscription(int client, int port,
- struct snd_seq_port_subscribe *info, int evtype);
-
-extern int seq_client_load[15];
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_compat.c b/ANDROID_3.4.5/sound/core/seq/seq_compat.c
deleted file mode 100644
index 81f7c109..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_compat.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for sequencer API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/* This file included from seq.c */
-
-#include <linux/compat.h>
-#include <linux/slab.h>
-
-struct snd_seq_port_info32 {
- struct snd_seq_addr addr; /* client/port numbers */
- char name[64]; /* port name */
-
- u32 capability; /* port capability bits */
- u32 type; /* port type bits */
- s32 midi_channels; /* channels per MIDI port */
- s32 midi_voices; /* voices per MIDI port */
- s32 synth_voices; /* voices per SYNTH port */
-
- s32 read_use; /* R/O: subscribers for output (from this port) */
- s32 write_use; /* R/O: subscribers for input (to this port) */
-
- u32 kernel; /* reserved for kernel use (must be NULL) */
- u32 flags; /* misc. conditioning */
- unsigned char time_queue; /* queue # for timestamping */
- char reserved[59]; /* for future use */
-};
-
-static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned int cmd,
- struct snd_seq_port_info32 __user *data32)
-{
- int err = -EFAULT;
- struct snd_seq_port_info *data;
- mm_segment_t fs;
-
- data = memdup_user(data32, sizeof(*data32));
- if (IS_ERR(data))
- return PTR_ERR(data);
-
- if (get_user(data->flags, &data32->flags) ||
- get_user(data->time_queue, &data32->time_queue))
- goto error;
- data->kernel = NULL;
-
- fs = snd_enter_user();
- err = snd_seq_do_ioctl(client, cmd, data);
- snd_leave_user(fs);
- if (err < 0)
- goto error;
-
- if (copy_to_user(data32, data, sizeof(*data32)) ||
- put_user(data->flags, &data32->flags) ||
- put_user(data->time_queue, &data32->time_queue))
- err = -EFAULT;
-
- error:
- kfree(data);
- return err;
-}
-
-
-
-/*
- */
-
-enum {
- SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct snd_seq_port_info32),
- SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct snd_seq_port_info32),
- SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct snd_seq_port_info32),
- SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct snd_seq_port_info32),
- SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct snd_seq_port_info32),
-};
-
-static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct snd_seq_client *client = file->private_data;
- void __user *argp = compat_ptr(arg);
-
- if (snd_BUG_ON(!client))
- return -ENXIO;
-
- switch (cmd) {
- case SNDRV_SEQ_IOCTL_PVERSION:
- case SNDRV_SEQ_IOCTL_CLIENT_ID:
- case SNDRV_SEQ_IOCTL_SYSTEM_INFO:
- case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO:
- case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO:
- case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT:
- case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT:
- case SNDRV_SEQ_IOCTL_CREATE_QUEUE:
- case SNDRV_SEQ_IOCTL_DELETE_QUEUE:
- case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO:
- case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO:
- case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE:
- case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS:
- case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO:
- case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO:
- case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER:
- case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER:
- case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT:
- case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT:
- case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL:
- case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL:
- case SNDRV_SEQ_IOCTL_REMOVE_EVENTS:
- case SNDRV_SEQ_IOCTL_QUERY_SUBS:
- case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION:
- case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT:
- case SNDRV_SEQ_IOCTL_RUNNING_MODE:
- return snd_seq_do_ioctl(client, cmd, argp);
- case SNDRV_SEQ_IOCTL_CREATE_PORT32:
- return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp);
- case SNDRV_SEQ_IOCTL_DELETE_PORT32:
- return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp);
- case SNDRV_SEQ_IOCTL_GET_PORT_INFO32:
- return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp);
- case SNDRV_SEQ_IOCTL_SET_PORT_INFO32:
- return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp);
- case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32:
- return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp);
- }
- return -ENOIOCTLCMD;
-}
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_device.c b/ANDROID_3.4.5/sound/core/seq/seq_device.c
deleted file mode 100644
index 5cf8d65e..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_device.c
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * ALSA sequencer device management
- * Copyright (c) 1999 by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- *----------------------------------------------------------------
- *
- * This device handler separates the card driver module from sequencer
- * stuff (sequencer core, synth drivers, etc), so that user can avoid
- * to spend unnecessary resources e.g. if he needs only listening to
- * MP3s.
- *
- * The card (or lowlevel) driver creates a sequencer device entry
- * via snd_seq_device_new(). This is an entry pointer to communicate
- * with the sequencer device "driver", which is involved with the
- * actual part to communicate with the sequencer core.
- * Each sequencer device entry has an id string and the corresponding
- * driver with the same id is loaded when required. For example,
- * lowlevel codes to access emu8000 chip on sbawe card are included in
- * emu8000-synth module. To activate this module, the hardware
- * resources like i/o port are passed via snd_seq_device argument.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/info.h>
-#include <sound/seq_device.h>
-#include <sound/seq_kernel.h>
-#include <sound/initval.h>
-#include <linux/kmod.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("ALSA sequencer device management");
-MODULE_LICENSE("GPL");
-
-/* driver state */
-#define DRIVER_EMPTY 0
-#define DRIVER_LOADED (1<<0)
-#define DRIVER_REQUESTED (1<<1)
-#define DRIVER_LOCKED (1<<2)
-
-struct ops_list {
- char id[ID_LEN]; /* driver id */
- int driver; /* driver state */
- int used; /* reference counter */
- int argsize; /* argument size */
-
- /* operators */
- struct snd_seq_dev_ops ops;
-
- /* registred devices */
- struct list_head dev_list; /* list of devices */
- int num_devices; /* number of associated devices */
- int num_init_devices; /* number of initialized devices */
- struct mutex reg_mutex;
-
- struct list_head list; /* next driver */
-};
-
-
-static LIST_HEAD(opslist);
-static int num_ops;
-static DEFINE_MUTEX(ops_mutex);
-#ifdef CONFIG_PROC_FS
-static struct snd_info_entry *info_entry;
-#endif
-
-/*
- * prototypes
- */
-static int snd_seq_device_free(struct snd_seq_device *dev);
-static int snd_seq_device_dev_free(struct snd_device *device);
-static int snd_seq_device_dev_register(struct snd_device *device);
-static int snd_seq_device_dev_disconnect(struct snd_device *device);
-
-static int init_device(struct snd_seq_device *dev, struct ops_list *ops);
-static int free_device(struct snd_seq_device *dev, struct ops_list *ops);
-static struct ops_list *find_driver(char *id, int create_if_empty);
-static struct ops_list *create_driver(char *id);
-static void unlock_driver(struct ops_list *ops);
-static void remove_drivers(void);
-
-/*
- * show all drivers and their status
- */
-
-#ifdef CONFIG_PROC_FS
-static void snd_seq_device_info(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct ops_list *ops;
-
- mutex_lock(&ops_mutex);
- list_for_each_entry(ops, &opslist, list) {
- snd_iprintf(buffer, "snd-%s%s%s%s,%d\n",
- ops->id,
- ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""),
- ops->driver & DRIVER_REQUESTED ? ",requested" : "",
- ops->driver & DRIVER_LOCKED ? ",locked" : "",
- ops->num_devices);
- }
- mutex_unlock(&ops_mutex);
-}
-#endif
-
-/*
- * load all registered drivers (called from seq_clientmgr.c)
- */
-
-#ifdef CONFIG_MODULES
-/* avoid auto-loading during module_init() */
-static int snd_seq_in_init;
-void snd_seq_autoload_lock(void)
-{
- snd_seq_in_init++;
-}
-
-void snd_seq_autoload_unlock(void)
-{
- snd_seq_in_init--;
-}
-#endif
-
-void snd_seq_device_load_drivers(void)
-{
-#ifdef CONFIG_MODULES
- struct ops_list *ops;
-
- /* Calling request_module during module_init()
- * may cause blocking.
- */
- if (snd_seq_in_init)
- return;
-
- mutex_lock(&ops_mutex);
- list_for_each_entry(ops, &opslist, list) {
- if (! (ops->driver & DRIVER_LOADED) &&
- ! (ops->driver & DRIVER_REQUESTED)) {
- ops->used++;
- mutex_unlock(&ops_mutex);
- ops->driver |= DRIVER_REQUESTED;
- request_module("snd-%s", ops->id);
- mutex_lock(&ops_mutex);
- ops->used--;
- }
- }
- mutex_unlock(&ops_mutex);
-#endif
-}
-
-/*
- * register a sequencer device
- * card = card info (NULL allowed)
- * device = device number (if any)
- * id = id of driver
- * result = return pointer (NULL allowed if unnecessary)
- */
-int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
- struct snd_seq_device **result)
-{
- struct snd_seq_device *dev;
- struct ops_list *ops;
- int err;
- static struct snd_device_ops dops = {
- .dev_free = snd_seq_device_dev_free,
- .dev_register = snd_seq_device_dev_register,
- .dev_disconnect = snd_seq_device_dev_disconnect,
- };
-
- if (result)
- *result = NULL;
-
- if (snd_BUG_ON(!id))
- return -EINVAL;
-
- ops = find_driver(id, 1);
- if (ops == NULL)
- return -ENOMEM;
-
- dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL);
- if (dev == NULL) {
- unlock_driver(ops);
- return -ENOMEM;
- }
-
- /* set up device info */
- dev->card = card;
- dev->device = device;
- strlcpy(dev->id, id, sizeof(dev->id));
- dev->argsize = argsize;
- dev->status = SNDRV_SEQ_DEVICE_FREE;
-
- /* add this device to the list */
- mutex_lock(&ops->reg_mutex);
- list_add_tail(&dev->list, &ops->dev_list);
- ops->num_devices++;
- mutex_unlock(&ops->reg_mutex);
-
- unlock_driver(ops);
-
- if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) {
- snd_seq_device_free(dev);
- return err;
- }
-
- if (result)
- *result = dev;
-
- return 0;
-}
-
-/*
- * free the existing device
- */
-static int snd_seq_device_free(struct snd_seq_device *dev)
-{
- struct ops_list *ops;
-
- if (snd_BUG_ON(!dev))
- return -EINVAL;
-
- ops = find_driver(dev->id, 0);
- if (ops == NULL)
- return -ENXIO;
-
- /* remove the device from the list */
- mutex_lock(&ops->reg_mutex);
- list_del(&dev->list);
- ops->num_devices--;
- mutex_unlock(&ops->reg_mutex);
-
- free_device(dev, ops);
- if (dev->private_free)
- dev->private_free(dev);
- kfree(dev);
-
- unlock_driver(ops);
-
- return 0;
-}
-
-static int snd_seq_device_dev_free(struct snd_device *device)
-{
- struct snd_seq_device *dev = device->device_data;
- return snd_seq_device_free(dev);
-}
-
-/*
- * register the device
- */
-static int snd_seq_device_dev_register(struct snd_device *device)
-{
- struct snd_seq_device *dev = device->device_data;
- struct ops_list *ops;
-
- ops = find_driver(dev->id, 0);
- if (ops == NULL)
- return -ENOENT;
-
- /* initialize this device if the corresponding driver was
- * already loaded
- */
- if (ops->driver & DRIVER_LOADED)
- init_device(dev, ops);
-
- unlock_driver(ops);
- return 0;
-}
-
-/*
- * disconnect the device
- */
-static int snd_seq_device_dev_disconnect(struct snd_device *device)
-{
- struct snd_seq_device *dev = device->device_data;
- struct ops_list *ops;
-
- ops = find_driver(dev->id, 0);
- if (ops == NULL)
- return -ENOENT;
-
- free_device(dev, ops);
-
- unlock_driver(ops);
- return 0;
-}
-
-/*
- * register device driver
- * id = driver id
- * entry = driver operators - duplicated to each instance
- */
-int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
- int argsize)
-{
- struct ops_list *ops;
- struct snd_seq_device *dev;
-
- if (id == NULL || entry == NULL ||
- entry->init_device == NULL || entry->free_device == NULL)
- return -EINVAL;
-
- snd_seq_autoload_lock();
- ops = find_driver(id, 1);
- if (ops == NULL) {
- snd_seq_autoload_unlock();
- return -ENOMEM;
- }
- if (ops->driver & DRIVER_LOADED) {
- snd_printk(KERN_WARNING "driver_register: driver '%s' already exists\n", id);
- unlock_driver(ops);
- snd_seq_autoload_unlock();
- return -EBUSY;
- }
-
- mutex_lock(&ops->reg_mutex);
- /* copy driver operators */
- ops->ops = *entry;
- ops->driver |= DRIVER_LOADED;
- ops->argsize = argsize;
-
- /* initialize existing devices if necessary */
- list_for_each_entry(dev, &ops->dev_list, list) {
- init_device(dev, ops);
- }
- mutex_unlock(&ops->reg_mutex);
-
- unlock_driver(ops);
- snd_seq_autoload_unlock();
-
- return 0;
-}
-
-
-/*
- * create driver record
- */
-static struct ops_list * create_driver(char *id)
-{
- struct ops_list *ops;
-
- ops = kzalloc(sizeof(*ops), GFP_KERNEL);
- if (ops == NULL)
- return ops;
-
- /* set up driver entry */
- strlcpy(ops->id, id, sizeof(ops->id));
- mutex_init(&ops->reg_mutex);
- /*
- * The ->reg_mutex locking rules are per-driver, so we create
- * separate per-driver lock classes:
- */
- lockdep_set_class(&ops->reg_mutex, (struct lock_class_key *)id);
-
- ops->driver = DRIVER_EMPTY;
- INIT_LIST_HEAD(&ops->dev_list);
- /* lock this instance */
- ops->used = 1;
-
- /* register driver entry */
- mutex_lock(&ops_mutex);
- list_add_tail(&ops->list, &opslist);
- num_ops++;
- mutex_unlock(&ops_mutex);
-
- return ops;
-}
-
-
-/*
- * unregister the specified driver
- */
-int snd_seq_device_unregister_driver(char *id)
-{
- struct ops_list *ops;
- struct snd_seq_device *dev;
-
- ops = find_driver(id, 0);
- if (ops == NULL)
- return -ENXIO;
- if (! (ops->driver & DRIVER_LOADED) ||
- (ops->driver & DRIVER_LOCKED)) {
- snd_printk(KERN_ERR "driver_unregister: cannot unload driver '%s': status=%x\n",
- id, ops->driver);
- unlock_driver(ops);
- return -EBUSY;
- }
-
- /* close and release all devices associated with this driver */
- mutex_lock(&ops->reg_mutex);
- ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */
- list_for_each_entry(dev, &ops->dev_list, list) {
- free_device(dev, ops);
- }
-
- ops->driver = 0;
- if (ops->num_init_devices > 0)
- snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n",
- ops->num_init_devices);
- mutex_unlock(&ops->reg_mutex);
-
- unlock_driver(ops);
-
- /* remove empty driver entries */
- remove_drivers();
-
- return 0;
-}
-
-
-/*
- * remove empty driver entries
- */
-static void remove_drivers(void)
-{
- struct list_head *head;
-
- mutex_lock(&ops_mutex);
- head = opslist.next;
- while (head != &opslist) {
- struct ops_list *ops = list_entry(head, struct ops_list, list);
- if (! (ops->driver & DRIVER_LOADED) &&
- ops->used == 0 && ops->num_devices == 0) {
- head = head->next;
- list_del(&ops->list);
- kfree(ops);
- num_ops--;
- } else
- head = head->next;
- }
- mutex_unlock(&ops_mutex);
-}
-
-/*
- * initialize the device - call init_device operator
- */
-static int init_device(struct snd_seq_device *dev, struct ops_list *ops)
-{
- if (! (ops->driver & DRIVER_LOADED))
- return 0; /* driver is not loaded yet */
- if (dev->status != SNDRV_SEQ_DEVICE_FREE)
- return 0; /* already initialized */
- if (ops->argsize != dev->argsize) {
- snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n",
- dev->name, ops->id, ops->argsize, dev->argsize);
- return -EINVAL;
- }
- if (ops->ops.init_device(dev) >= 0) {
- dev->status = SNDRV_SEQ_DEVICE_REGISTERED;
- ops->num_init_devices++;
- } else {
- snd_printk(KERN_ERR "init_device failed: %s: %s\n",
- dev->name, dev->id);
- }
-
- return 0;
-}
-
-/*
- * release the device - call free_device operator
- */
-static int free_device(struct snd_seq_device *dev, struct ops_list *ops)
-{
- int result;
-
- if (! (ops->driver & DRIVER_LOADED))
- return 0; /* driver is not loaded yet */
- if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED)
- return 0; /* not registered */
- if (ops->argsize != dev->argsize) {
- snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n",
- dev->name, ops->id, ops->argsize, dev->argsize);
- return -EINVAL;
- }
- if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) {
- dev->status = SNDRV_SEQ_DEVICE_FREE;
- dev->driver_data = NULL;
- ops->num_init_devices--;
- } else {
- snd_printk(KERN_ERR "free_device failed: %s: %s\n",
- dev->name, dev->id);
- }
-
- return 0;
-}
-
-/*
- * find the matching driver with given id
- */
-static struct ops_list * find_driver(char *id, int create_if_empty)
-{
- struct ops_list *ops;
-
- mutex_lock(&ops_mutex);
- list_for_each_entry(ops, &opslist, list) {
- if (strcmp(ops->id, id) == 0) {
- ops->used++;
- mutex_unlock(&ops_mutex);
- return ops;
- }
- }
- mutex_unlock(&ops_mutex);
- if (create_if_empty)
- return create_driver(id);
- return NULL;
-}
-
-static void unlock_driver(struct ops_list *ops)
-{
- mutex_lock(&ops_mutex);
- ops->used--;
- mutex_unlock(&ops_mutex);
-}
-
-
-/*
- * module part
- */
-
-static int __init alsa_seq_device_init(void)
-{
-#ifdef CONFIG_PROC_FS
- info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers",
- snd_seq_root);
- if (info_entry == NULL)
- return -ENOMEM;
- info_entry->content = SNDRV_INFO_CONTENT_TEXT;
- info_entry->c.text.read = snd_seq_device_info;
- if (snd_info_register(info_entry) < 0) {
- snd_info_free_entry(info_entry);
- return -ENOMEM;
- }
-#endif
- return 0;
-}
-
-static void __exit alsa_seq_device_exit(void)
-{
- remove_drivers();
-#ifdef CONFIG_PROC_FS
- snd_info_free_entry(info_entry);
-#endif
- if (num_ops)
- snd_printk(KERN_ERR "drivers not released (%d)\n", num_ops);
-}
-
-module_init(alsa_seq_device_init)
-module_exit(alsa_seq_device_exit)
-
-EXPORT_SYMBOL(snd_seq_device_load_drivers);
-EXPORT_SYMBOL(snd_seq_device_new);
-EXPORT_SYMBOL(snd_seq_device_register_driver);
-EXPORT_SYMBOL(snd_seq_device_unregister_driver);
-EXPORT_SYMBOL(snd_seq_autoload_lock);
-EXPORT_SYMBOL(snd_seq_autoload_unlock);
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_dummy.c b/ANDROID_3.4.5/sound/core/seq/seq_dummy.c
deleted file mode 100644
index dbc55071..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_dummy.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * ALSA sequencer MIDI-through client
- * Copyright (c) 1999-2000 by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include "seq_clientmgr.h"
-#include <sound/initval.h>
-#include <sound/asoundef.h>
-
-/*
-
- Sequencer MIDI-through client
-
- This gives a simple midi-through client. All the normal input events
- are redirected to output port immediately.
- The routing can be done via aconnect program in alsa-utils.
-
- Each client has a static client number 62 (= SNDRV_SEQ_CLIENT_DUMMY).
- If you want to auto-load this module, you may add the following alias
- in your /etc/conf.modules file.
-
- alias snd-seq-client-62 snd-seq-dummy
-
- The module is loaded on demand for client 62, or /proc/asound/seq/
- is accessed. If you don't need this module to be loaded, alias
- snd-seq-client-62 as "off". This will help modprobe.
-
- The number of ports to be created can be specified via the module
- parameter "ports". For example, to create four ports, add the
- following option in a configuration file under /etc/modprobe.d/:
-
- option snd-seq-dummy ports=4
-
- The model option "duplex=1" enables duplex operation to the port.
- In duplex mode, a pair of ports are created instead of single port,
- and events are tunneled between pair-ports. For example, input to
- port A is sent to output port of another port B and vice versa.
- In duplex mode, each port has DUPLEX capability.
-
- */
-
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("ALSA sequencer MIDI-through client");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY));
-
-static int ports = 1;
-static bool duplex;
-
-module_param(ports, int, 0444);
-MODULE_PARM_DESC(ports, "number of ports to be created");
-module_param(duplex, bool, 0444);
-MODULE_PARM_DESC(duplex, "create DUPLEX ports");
-
-struct snd_seq_dummy_port {
- int client;
- int port;
- int duplex;
- int connect;
-};
-
-static int my_client = -1;
-
-/*
- * unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events
- * to subscribers.
- * Note: this callback is called only after all subscribers are removed.
- */
-static int
-dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info)
-{
- struct snd_seq_dummy_port *p;
- int i;
- struct snd_seq_event ev;
-
- p = private_data;
- memset(&ev, 0, sizeof(ev));
- if (p->duplex)
- ev.source.port = p->connect;
- else
- ev.source.port = p->port;
- ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
- for (i = 0; i < 16; i++) {
- ev.data.control.channel = i;
- ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF;
- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0);
- ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS;
- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0);
- }
- return 0;
-}
-
-/*
- * event input callback - just redirect events to subscribers
- */
-static int
-dummy_input(struct snd_seq_event *ev, int direct, void *private_data,
- int atomic, int hop)
-{
- struct snd_seq_dummy_port *p;
- struct snd_seq_event tmpev;
-
- p = private_data;
- if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM ||
- ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
- return 0; /* ignore system messages */
- tmpev = *ev;
- if (p->duplex)
- tmpev.source.port = p->connect;
- else
- tmpev.source.port = p->port;
- tmpev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- return snd_seq_kernel_client_dispatch(p->client, &tmpev, atomic, hop);
-}
-
-/*
- * free_private callback
- */
-static void
-dummy_free(void *private_data)
-{
- kfree(private_data);
-}
-
-/*
- * create a port
- */
-static struct snd_seq_dummy_port __init *
-create_port(int idx, int type)
-{
- struct snd_seq_port_info pinfo;
- struct snd_seq_port_callback pcb;
- struct snd_seq_dummy_port *rec;
-
- if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL)
- return NULL;
-
- rec->client = my_client;
- rec->duplex = duplex;
- rec->connect = 0;
- memset(&pinfo, 0, sizeof(pinfo));
- pinfo.addr.client = my_client;
- if (duplex)
- sprintf(pinfo.name, "Midi Through Port-%d:%c", idx,
- (type ? 'B' : 'A'));
- else
- sprintf(pinfo.name, "Midi Through Port-%d", idx);
- pinfo.capability = SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
- pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
- if (duplex)
- pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
- pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
- | SNDRV_SEQ_PORT_TYPE_SOFTWARE
- | SNDRV_SEQ_PORT_TYPE_PORT;
- memset(&pcb, 0, sizeof(pcb));
- pcb.owner = THIS_MODULE;
- pcb.unuse = dummy_unuse;
- pcb.event_input = dummy_input;
- pcb.private_free = dummy_free;
- pcb.private_data = rec;
- pinfo.kernel = &pcb;
- if (snd_seq_kernel_client_ctl(my_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo) < 0) {
- kfree(rec);
- return NULL;
- }
- rec->port = pinfo.addr.port;
- return rec;
-}
-
-/*
- * register client and create ports
- */
-static int __init
-register_client(void)
-{
- struct snd_seq_dummy_port *rec1, *rec2;
- int i;
-
- if (ports < 1) {
- snd_printk(KERN_ERR "invalid number of ports %d\n", ports);
- return -EINVAL;
- }
-
- /* create client */
- my_client = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_DUMMY,
- "Midi Through");
- if (my_client < 0)
- return my_client;
-
- /* create ports */
- for (i = 0; i < ports; i++) {
- rec1 = create_port(i, 0);
- if (rec1 == NULL) {
- snd_seq_delete_kernel_client(my_client);
- return -ENOMEM;
- }
- if (duplex) {
- rec2 = create_port(i, 1);
- if (rec2 == NULL) {
- snd_seq_delete_kernel_client(my_client);
- return -ENOMEM;
- }
- rec1->connect = rec2->port;
- rec2->connect = rec1->port;
- }
- }
-
- return 0;
-}
-
-/*
- * delete client if exists
- */
-static void __exit
-delete_client(void)
-{
- if (my_client >= 0)
- snd_seq_delete_kernel_client(my_client);
-}
-
-/*
- * Init part
- */
-
-static int __init alsa_seq_dummy_init(void)
-{
- int err;
- snd_seq_autoload_lock();
- err = register_client();
- snd_seq_autoload_unlock();
- return err;
-}
-
-static void __exit alsa_seq_dummy_exit(void)
-{
- delete_client();
-}
-
-module_init(alsa_seq_dummy_init)
-module_exit(alsa_seq_dummy_exit)
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_fifo.c b/ANDROID_3.4.5/sound/core/seq/seq_fifo.c
deleted file mode 100644
index 0d75afa7..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_fifo.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * ALSA sequencer FIFO
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <sound/core.h>
-#include <linux/slab.h>
-#include "seq_fifo.h"
-#include "seq_lock.h"
-
-
-/* FIFO */
-
-/* create new fifo */
-struct snd_seq_fifo *snd_seq_fifo_new(int poolsize)
-{
- struct snd_seq_fifo *f;
-
- f = kzalloc(sizeof(*f), GFP_KERNEL);
- if (f == NULL) {
- snd_printd("malloc failed for snd_seq_fifo_new() \n");
- return NULL;
- }
-
- f->pool = snd_seq_pool_new(poolsize);
- if (f->pool == NULL) {
- kfree(f);
- return NULL;
- }
- if (snd_seq_pool_init(f->pool) < 0) {
- snd_seq_pool_delete(&f->pool);
- kfree(f);
- return NULL;
- }
-
- spin_lock_init(&f->lock);
- snd_use_lock_init(&f->use_lock);
- init_waitqueue_head(&f->input_sleep);
- atomic_set(&f->overflow, 0);
-
- f->head = NULL;
- f->tail = NULL;
- f->cells = 0;
-
- return f;
-}
-
-void snd_seq_fifo_delete(struct snd_seq_fifo **fifo)
-{
- struct snd_seq_fifo *f;
-
- if (snd_BUG_ON(!fifo))
- return;
- f = *fifo;
- if (snd_BUG_ON(!f))
- return;
- *fifo = NULL;
-
- snd_seq_fifo_clear(f);
-
- /* wake up clients if any */
- if (waitqueue_active(&f->input_sleep))
- wake_up(&f->input_sleep);
-
- /* release resources...*/
- /*....................*/
-
- if (f->pool) {
- snd_seq_pool_done(f->pool);
- snd_seq_pool_delete(&f->pool);
- }
-
- kfree(f);
-}
-
-static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f);
-
-/* clear queue */
-void snd_seq_fifo_clear(struct snd_seq_fifo *f)
-{
- struct snd_seq_event_cell *cell;
- unsigned long flags;
-
- /* clear overflow flag */
- atomic_set(&f->overflow, 0);
-
- snd_use_lock_sync(&f->use_lock);
- spin_lock_irqsave(&f->lock, flags);
- /* drain the fifo */
- while ((cell = fifo_cell_out(f)) != NULL) {
- snd_seq_cell_free(cell);
- }
- spin_unlock_irqrestore(&f->lock, flags);
-}
-
-
-/* enqueue event to fifo */
-int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
- struct snd_seq_event *event)
-{
- struct snd_seq_event_cell *cell;
- unsigned long flags;
- int err;
-
- if (snd_BUG_ON(!f))
- return -EINVAL;
-
- snd_use_lock_use(&f->use_lock);
- err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */
- if (err < 0) {
- if (err == -ENOMEM)
- atomic_inc(&f->overflow);
- snd_use_lock_free(&f->use_lock);
- return err;
- }
-
- /* append new cells to fifo */
- spin_lock_irqsave(&f->lock, flags);
- if (f->tail != NULL)
- f->tail->next = cell;
- f->tail = cell;
- if (f->head == NULL)
- f->head = cell;
- f->cells++;
- spin_unlock_irqrestore(&f->lock, flags);
-
- /* wakeup client */
- if (waitqueue_active(&f->input_sleep))
- wake_up(&f->input_sleep);
-
- snd_use_lock_free(&f->use_lock);
-
- return 0; /* success */
-
-}
-
-/* dequeue cell from fifo */
-static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f)
-{
- struct snd_seq_event_cell *cell;
-
- if ((cell = f->head) != NULL) {
- f->head = cell->next;
-
- /* reset tail if this was the last element */
- if (f->tail == cell)
- f->tail = NULL;
-
- cell->next = NULL;
- f->cells--;
- }
-
- return cell;
-}
-
-/* dequeue cell from fifo and copy on user space */
-int snd_seq_fifo_cell_out(struct snd_seq_fifo *f,
- struct snd_seq_event_cell **cellp, int nonblock)
-{
- struct snd_seq_event_cell *cell;
- unsigned long flags;
- wait_queue_t wait;
-
- if (snd_BUG_ON(!f))
- return -EINVAL;
-
- *cellp = NULL;
- init_waitqueue_entry(&wait, current);
- spin_lock_irqsave(&f->lock, flags);
- while ((cell = fifo_cell_out(f)) == NULL) {
- if (nonblock) {
- /* non-blocking - return immediately */
- spin_unlock_irqrestore(&f->lock, flags);
- return -EAGAIN;
- }
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&f->input_sleep, &wait);
- spin_unlock_irq(&f->lock);
- schedule();
- spin_lock_irq(&f->lock);
- remove_wait_queue(&f->input_sleep, &wait);
- if (signal_pending(current)) {
- spin_unlock_irqrestore(&f->lock, flags);
- return -ERESTARTSYS;
- }
- }
- spin_unlock_irqrestore(&f->lock, flags);
- *cellp = cell;
-
- return 0;
-}
-
-
-void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f,
- struct snd_seq_event_cell *cell)
-{
- unsigned long flags;
-
- if (cell) {
- spin_lock_irqsave(&f->lock, flags);
- cell->next = f->head;
- f->head = cell;
- f->cells++;
- spin_unlock_irqrestore(&f->lock, flags);
- }
-}
-
-
-/* polling; return non-zero if queue is available */
-int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file,
- poll_table *wait)
-{
- poll_wait(file, &f->input_sleep, wait);
- return (f->cells > 0);
-}
-
-/* change the size of pool; all old events are removed */
-int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
-{
- unsigned long flags;
- struct snd_seq_pool *newpool, *oldpool;
- struct snd_seq_event_cell *cell, *next, *oldhead;
-
- if (snd_BUG_ON(!f || !f->pool))
- return -EINVAL;
-
- /* allocate new pool */
- newpool = snd_seq_pool_new(poolsize);
- if (newpool == NULL)
- return -ENOMEM;
- if (snd_seq_pool_init(newpool) < 0) {
- snd_seq_pool_delete(&newpool);
- return -ENOMEM;
- }
-
- spin_lock_irqsave(&f->lock, flags);
- /* remember old pool */
- oldpool = f->pool;
- oldhead = f->head;
- /* exchange pools */
- f->pool = newpool;
- f->head = NULL;
- f->tail = NULL;
- f->cells = 0;
- /* NOTE: overflow flag is not cleared */
- spin_unlock_irqrestore(&f->lock, flags);
-
- /* release cells in old pool */
- for (cell = oldhead; cell; cell = next) {
- next = cell->next;
- snd_seq_cell_free(cell);
- }
- snd_seq_pool_delete(&oldpool);
-
- return 0;
-}
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_fifo.h b/ANDROID_3.4.5/sound/core/seq/seq_fifo.h
deleted file mode 100644
index 062c446e..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_fifo.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * ALSA sequencer FIFO
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __SND_SEQ_FIFO_H
-#define __SND_SEQ_FIFO_H
-
-#include "seq_memory.h"
-#include "seq_lock.h"
-
-
-/* === FIFO === */
-
-struct snd_seq_fifo {
- struct snd_seq_pool *pool; /* FIFO pool */
- struct snd_seq_event_cell *head; /* pointer to head of fifo */
- struct snd_seq_event_cell *tail; /* pointer to tail of fifo */
- int cells;
- spinlock_t lock;
- snd_use_lock_t use_lock;
- wait_queue_head_t input_sleep;
- atomic_t overflow;
-
-};
-
-/* create new fifo (constructor) */
-struct snd_seq_fifo *snd_seq_fifo_new(int poolsize);
-
-/* delete fifo (destructor) */
-void snd_seq_fifo_delete(struct snd_seq_fifo **f);
-
-
-/* enqueue event to fifo */
-int snd_seq_fifo_event_in(struct snd_seq_fifo *f, struct snd_seq_event *event);
-
-/* lock fifo from release */
-#define snd_seq_fifo_lock(fifo) snd_use_lock_use(&(fifo)->use_lock)
-#define snd_seq_fifo_unlock(fifo) snd_use_lock_free(&(fifo)->use_lock)
-
-/* get a cell from fifo - fifo should be locked */
-int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, struct snd_seq_event_cell **cellp, int nonblock);
-
-/* free dequeued cell - fifo should be locked */
-void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f, struct snd_seq_event_cell *cell);
-
-/* clean up queue */
-void snd_seq_fifo_clear(struct snd_seq_fifo *f);
-
-/* polling */
-int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, poll_table *wait);
-
-/* resize pool in fifo */
-int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize);
-
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_info.c b/ANDROID_3.4.5/sound/core/seq/seq_info.c
deleted file mode 100644
index acf77694..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_info.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * ALSA sequencer /proc interface
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <sound/core.h>
-
-#include "seq_info.h"
-#include "seq_clientmgr.h"
-#include "seq_timer.h"
-
-#ifdef CONFIG_PROC_FS
-static struct snd_info_entry *queues_entry;
-static struct snd_info_entry *clients_entry;
-static struct snd_info_entry *timer_entry;
-
-
-static struct snd_info_entry * __init
-create_info_entry(char *name, void (*read)(struct snd_info_entry *,
- struct snd_info_buffer *))
-{
- struct snd_info_entry *entry;
-
- entry = snd_info_create_module_entry(THIS_MODULE, name, snd_seq_root);
- if (entry == NULL)
- return NULL;
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->c.text.read = read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- return NULL;
- }
- return entry;
-}
-
-/* create all our /proc entries */
-int __init snd_seq_info_init(void)
-{
- queues_entry = create_info_entry("queues",
- snd_seq_info_queues_read);
- clients_entry = create_info_entry("clients",
- snd_seq_info_clients_read);
- timer_entry = create_info_entry("timer", snd_seq_info_timer_read);
- return 0;
-}
-
-int __exit snd_seq_info_done(void)
-{
- snd_info_free_entry(queues_entry);
- snd_info_free_entry(clients_entry);
- snd_info_free_entry(timer_entry);
- return 0;
-}
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_info.h b/ANDROID_3.4.5/sound/core/seq/seq_info.h
deleted file mode 100644
index 4892a7f3..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_info.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * ALSA sequencer /proc info
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __SND_SEQ_INFO_H
-#define __SND_SEQ_INFO_H
-
-#include <sound/info.h>
-#include <sound/seq_kernel.h>
-
-void snd_seq_info_clients_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
-void snd_seq_info_timer_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
-void snd_seq_info_queues_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
-
-
-#ifdef CONFIG_PROC_FS
-int snd_seq_info_init( void );
-int snd_seq_info_done( void );
-#else
-static inline int snd_seq_info_init(void) { return 0; }
-static inline int snd_seq_info_done(void) { return 0; }
-#endif
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_lock.c b/ANDROID_3.4.5/sound/core/seq/seq_lock.c
deleted file mode 100644
index 2cfe50c7..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_lock.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Do sleep inside a spin-lock
- * Copyright (c) 1999 by Takashi Iwai <tiwai@suse.de>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/export.h>
-#include <sound/core.h>
-#include "seq_lock.h"
-
-#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG)
-
-/* wait until all locks are released */
-void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
-{
- int max_count = 5 * HZ;
-
- if (atomic_read(lockp) < 0) {
- printk(KERN_WARNING "seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line);
- return;
- }
- while (atomic_read(lockp) > 0) {
- if (max_count == 0) {
- snd_printk(KERN_WARNING "seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line);
- break;
- }
- schedule_timeout_uninterruptible(1);
- max_count--;
- }
-}
-
-EXPORT_SYMBOL(snd_use_lock_sync_helper);
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_lock.h b/ANDROID_3.4.5/sound/core/seq/seq_lock.h
deleted file mode 100644
index 54044bc2..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_lock.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef __SND_SEQ_LOCK_H
-#define __SND_SEQ_LOCK_H
-
-#include <linux/sched.h>
-
-#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG)
-
-typedef atomic_t snd_use_lock_t;
-
-/* initialize lock */
-#define snd_use_lock_init(lockp) atomic_set(lockp, 0)
-
-/* increment lock */
-#define snd_use_lock_use(lockp) atomic_inc(lockp)
-
-/* release lock */
-#define snd_use_lock_free(lockp) atomic_dec(lockp)
-
-/* wait until all locks are released */
-void snd_use_lock_sync_helper(snd_use_lock_t *lock, const char *file, int line);
-#define snd_use_lock_sync(lockp) snd_use_lock_sync_helper(lockp, __BASE_FILE__, __LINE__)
-
-#else /* SMP || CONFIG_SND_DEBUG */
-
-typedef spinlock_t snd_use_lock_t; /* dummy */
-#define snd_use_lock_init(lockp) /**/
-#define snd_use_lock_use(lockp) /**/
-#define snd_use_lock_free(lockp) /**/
-#define snd_use_lock_sync(lockp) /**/
-
-#endif /* SMP || CONFIG_SND_DEBUG */
-
-#endif /* __SND_SEQ_LOCK_H */
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_memory.c b/ANDROID_3.4.5/sound/core/seq/seq_memory.c
deleted file mode 100644
index f478f770..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_memory.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * ALSA sequencer Memory Manager
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@perex.cz>
- * 2000 by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <sound/core.h>
-
-#include <sound/seq_kernel.h>
-#include "seq_memory.h"
-#include "seq_queue.h"
-#include "seq_info.h"
-#include "seq_lock.h"
-
-static inline int snd_seq_pool_available(struct snd_seq_pool *pool)
-{
- return pool->total_elements - atomic_read(&pool->counter);
-}
-
-static inline int snd_seq_output_ok(struct snd_seq_pool *pool)
-{
- return snd_seq_pool_available(pool) >= pool->room;
-}
-
-/*
- * Variable length event:
- * The event like sysex uses variable length type.
- * The external data may be stored in three different formats.
- * 1) kernel space
- * This is the normal case.
- * ext.data.len = length
- * ext.data.ptr = buffer pointer
- * 2) user space
- * When an event is generated via read(), the external data is
- * kept in user space until expanded.
- * ext.data.len = length | SNDRV_SEQ_EXT_USRPTR
- * ext.data.ptr = userspace pointer
- * 3) chained cells
- * When the variable length event is enqueued (in prioq or fifo),
- * the external data is decomposed to several cells.
- * ext.data.len = length | SNDRV_SEQ_EXT_CHAINED
- * ext.data.ptr = the additiona cell head
- * -> cell.next -> cell.next -> ..
- */
-
-/*
- * exported:
- * call dump function to expand external data.
- */
-
-static int get_var_len(const struct snd_seq_event *event)
-{
- if ((event->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
- return -EINVAL;
-
- return event->data.ext.len & ~SNDRV_SEQ_EXT_MASK;
-}
-
-int snd_seq_dump_var_event(const struct snd_seq_event *event,
- snd_seq_dump_func_t func, void *private_data)
-{
- int len, err;
- struct snd_seq_event_cell *cell;
-
- if ((len = get_var_len(event)) <= 0)
- return len;
-
- if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
- char buf[32];
- char __user *curptr = (char __force __user *)event->data.ext.ptr;
- while (len > 0) {
- int size = sizeof(buf);
- if (len < size)
- size = len;
- if (copy_from_user(buf, curptr, size))
- return -EFAULT;
- err = func(private_data, buf, size);
- if (err < 0)
- return err;
- curptr += size;
- len -= size;
- }
- return 0;
- } if (! (event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) {
- return func(private_data, event->data.ext.ptr, len);
- }
-
- cell = (struct snd_seq_event_cell *)event->data.ext.ptr;
- for (; len > 0 && cell; cell = cell->next) {
- int size = sizeof(struct snd_seq_event);
- if (len < size)
- size = len;
- err = func(private_data, &cell->event, size);
- if (err < 0)
- return err;
- len -= size;
- }
- return 0;
-}
-
-EXPORT_SYMBOL(snd_seq_dump_var_event);
-
-
-/*
- * exported:
- * expand the variable length event to linear buffer space.
- */
-
-static int seq_copy_in_kernel(char **bufptr, const void *src, int size)
-{
- memcpy(*bufptr, src, size);
- *bufptr += size;
- return 0;
-}
-
-static int seq_copy_in_user(char __user **bufptr, const void *src, int size)
-{
- if (copy_to_user(*bufptr, src, size))
- return -EFAULT;
- *bufptr += size;
- return 0;
-}
-
-int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char *buf,
- int in_kernel, int size_aligned)
-{
- int len, newlen;
- int err;
-
- if ((len = get_var_len(event)) < 0)
- return len;
- newlen = len;
- if (size_aligned > 0)
- newlen = roundup(len, size_aligned);
- if (count < newlen)
- return -EAGAIN;
-
- if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
- if (! in_kernel)
- return -EINVAL;
- if (copy_from_user(buf, (void __force __user *)event->data.ext.ptr, len))
- return -EFAULT;
- return newlen;
- }
- err = snd_seq_dump_var_event(event,
- in_kernel ? (snd_seq_dump_func_t)seq_copy_in_kernel :
- (snd_seq_dump_func_t)seq_copy_in_user,
- &buf);
- return err < 0 ? err : newlen;
-}
-
-EXPORT_SYMBOL(snd_seq_expand_var_event);
-
-/*
- * release this cell, free extended data if available
- */
-
-static inline void free_cell(struct snd_seq_pool *pool,
- struct snd_seq_event_cell *cell)
-{
- cell->next = pool->free;
- pool->free = cell;
- atomic_dec(&pool->counter);
-}
-
-void snd_seq_cell_free(struct snd_seq_event_cell * cell)
-{
- unsigned long flags;
- struct snd_seq_pool *pool;
-
- if (snd_BUG_ON(!cell))
- return;
- pool = cell->pool;
- if (snd_BUG_ON(!pool))
- return;
-
- spin_lock_irqsave(&pool->lock, flags);
- free_cell(pool, cell);
- if (snd_seq_ev_is_variable(&cell->event)) {
- if (cell->event.data.ext.len & SNDRV_SEQ_EXT_CHAINED) {
- struct snd_seq_event_cell *curp, *nextptr;
- curp = cell->event.data.ext.ptr;
- for (; curp; curp = nextptr) {
- nextptr = curp->next;
- curp->next = pool->free;
- free_cell(pool, curp);
- }
- }
- }
- if (waitqueue_active(&pool->output_sleep)) {
- /* has enough space now? */
- if (snd_seq_output_ok(pool))
- wake_up(&pool->output_sleep);
- }
- spin_unlock_irqrestore(&pool->lock, flags);
-}
-
-
-/*
- * allocate an event cell.
- */
-static int snd_seq_cell_alloc(struct snd_seq_pool *pool,
- struct snd_seq_event_cell **cellp,
- int nonblock, struct file *file)
-{
- struct snd_seq_event_cell *cell;
- unsigned long flags;
- int err = -EAGAIN;
- wait_queue_t wait;
-
- if (pool == NULL)
- return -EINVAL;
-
- *cellp = NULL;
-
- init_waitqueue_entry(&wait, current);
- spin_lock_irqsave(&pool->lock, flags);
- if (pool->ptr == NULL) { /* not initialized */
- snd_printd("seq: pool is not initialized\n");
- err = -EINVAL;
- goto __error;
- }
- while (pool->free == NULL && ! nonblock && ! pool->closing) {
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&pool->output_sleep, &wait);
- spin_unlock_irq(&pool->lock);
- schedule();
- spin_lock_irq(&pool->lock);
- remove_wait_queue(&pool->output_sleep, &wait);
- /* interrupted? */
- if (signal_pending(current)) {
- err = -ERESTARTSYS;
- goto __error;
- }
- }
- if (pool->closing) { /* closing.. */
- err = -ENOMEM;
- goto __error;
- }
-
- cell = pool->free;
- if (cell) {
- int used;
- pool->free = cell->next;
- atomic_inc(&pool->counter);
- used = atomic_read(&pool->counter);
- if (pool->max_used < used)
- pool->max_used = used;
- pool->event_alloc_success++;
- /* clear cell pointers */
- cell->next = NULL;
- err = 0;
- } else
- pool->event_alloc_failures++;
- *cellp = cell;
-
-__error:
- spin_unlock_irqrestore(&pool->lock, flags);
- return err;
-}
-
-
-/*
- * duplicate the event to a cell.
- * if the event has external data, the data is decomposed to additional
- * cells.
- */
-int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
- struct snd_seq_event_cell **cellp, int nonblock,
- struct file *file)
-{
- int ncells, err;
- unsigned int extlen;
- struct snd_seq_event_cell *cell;
-
- *cellp = NULL;
-
- ncells = 0;
- extlen = 0;
- if (snd_seq_ev_is_variable(event)) {
- extlen = event->data.ext.len & ~SNDRV_SEQ_EXT_MASK;
- ncells = (extlen + sizeof(struct snd_seq_event) - 1) / sizeof(struct snd_seq_event);
- }
- if (ncells >= pool->total_elements)
- return -ENOMEM;
-
- err = snd_seq_cell_alloc(pool, &cell, nonblock, file);
- if (err < 0)
- return err;
-
- /* copy the event */
- cell->event = *event;
-
- /* decompose */
- if (snd_seq_ev_is_variable(event)) {
- int len = extlen;
- int is_chained = event->data.ext.len & SNDRV_SEQ_EXT_CHAINED;
- int is_usrptr = event->data.ext.len & SNDRV_SEQ_EXT_USRPTR;
- struct snd_seq_event_cell *src, *tmp, *tail;
- char *buf;
-
- cell->event.data.ext.len = extlen | SNDRV_SEQ_EXT_CHAINED;
- cell->event.data.ext.ptr = NULL;
-
- src = (struct snd_seq_event_cell *)event->data.ext.ptr;
- buf = (char *)event->data.ext.ptr;
- tail = NULL;
-
- while (ncells-- > 0) {
- int size = sizeof(struct snd_seq_event);
- if (len < size)
- size = len;
- err = snd_seq_cell_alloc(pool, &tmp, nonblock, file);
- if (err < 0)
- goto __error;
- if (cell->event.data.ext.ptr == NULL)
- cell->event.data.ext.ptr = tmp;
- if (tail)
- tail->next = tmp;
- tail = tmp;
- /* copy chunk */
- if (is_chained && src) {
- tmp->event = src->event;
- src = src->next;
- } else if (is_usrptr) {
- if (copy_from_user(&tmp->event, (char __force __user *)buf, size)) {
- err = -EFAULT;
- goto __error;
- }
- } else {
- memcpy(&tmp->event, buf, size);
- }
- buf += size;
- len -= size;
- }
- }
-
- *cellp = cell;
- return 0;
-
-__error:
- snd_seq_cell_free(cell);
- return err;
-}
-
-
-/* poll wait */
-int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file,
- poll_table *wait)
-{
- poll_wait(file, &pool->output_sleep, wait);
- return snd_seq_output_ok(pool);
-}
-
-
-/* allocate room specified number of events */
-int snd_seq_pool_init(struct snd_seq_pool *pool)
-{
- int cell;
- struct snd_seq_event_cell *cellptr;
- unsigned long flags;
-
- if (snd_BUG_ON(!pool))
- return -EINVAL;
- if (pool->ptr) /* should be atomic? */
- return 0;
-
- pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
- if (pool->ptr == NULL) {
- snd_printd("seq: malloc for sequencer events failed\n");
- return -ENOMEM;
- }
-
- /* add new cells to the free cell list */
- spin_lock_irqsave(&pool->lock, flags);
- pool->free = NULL;
-
- for (cell = 0; cell < pool->size; cell++) {
- cellptr = pool->ptr + cell;
- cellptr->pool = pool;
- cellptr->next = pool->free;
- pool->free = cellptr;
- }
- pool->room = (pool->size + 1) / 2;
-
- /* init statistics */
- pool->max_used = 0;
- pool->total_elements = pool->size;
- spin_unlock_irqrestore(&pool->lock, flags);
- return 0;
-}
-
-/* remove events */
-int snd_seq_pool_done(struct snd_seq_pool *pool)
-{
- unsigned long flags;
- struct snd_seq_event_cell *ptr;
- int max_count = 5 * HZ;
-
- if (snd_BUG_ON(!pool))
- return -EINVAL;
-
- /* wait for closing all threads */
- spin_lock_irqsave(&pool->lock, flags);
- pool->closing = 1;
- spin_unlock_irqrestore(&pool->lock, flags);
-
- if (waitqueue_active(&pool->output_sleep))
- wake_up(&pool->output_sleep);
-
- while (atomic_read(&pool->counter) > 0) {
- if (max_count == 0) {
- snd_printk(KERN_WARNING "snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter));
- break;
- }
- schedule_timeout_uninterruptible(1);
- max_count--;
- }
-
- /* release all resources */
- spin_lock_irqsave(&pool->lock, flags);
- ptr = pool->ptr;
- pool->ptr = NULL;
- pool->free = NULL;
- pool->total_elements = 0;
- spin_unlock_irqrestore(&pool->lock, flags);
-
- vfree(ptr);
-
- spin_lock_irqsave(&pool->lock, flags);
- pool->closing = 0;
- spin_unlock_irqrestore(&pool->lock, flags);
-
- return 0;
-}
-
-
-/* init new memory pool */
-struct snd_seq_pool *snd_seq_pool_new(int poolsize)
-{
- struct snd_seq_pool *pool;
-
- /* create pool block */
- pool = kzalloc(sizeof(*pool), GFP_KERNEL);
- if (pool == NULL) {
- snd_printd("seq: malloc failed for pool\n");
- return NULL;
- }
- spin_lock_init(&pool->lock);
- pool->ptr = NULL;
- pool->free = NULL;
- pool->total_elements = 0;
- atomic_set(&pool->counter, 0);
- pool->closing = 0;
- init_waitqueue_head(&pool->output_sleep);
-
- pool->size = poolsize;
-
- /* init statistics */
- pool->max_used = 0;
- return pool;
-}
-
-/* remove memory pool */
-int snd_seq_pool_delete(struct snd_seq_pool **ppool)
-{
- struct snd_seq_pool *pool = *ppool;
-
- *ppool = NULL;
- if (pool == NULL)
- return 0;
- snd_seq_pool_done(pool);
- kfree(pool);
- return 0;
-}
-
-/* initialize sequencer memory */
-int __init snd_sequencer_memory_init(void)
-{
- return 0;
-}
-
-/* release sequencer memory */
-void __exit snd_sequencer_memory_done(void)
-{
-}
-
-
-/* exported to seq_clientmgr.c */
-void snd_seq_info_pool(struct snd_info_buffer *buffer,
- struct snd_seq_pool *pool, char *space)
-{
- if (pool == NULL)
- return;
- snd_iprintf(buffer, "%sPool size : %d\n", space, pool->total_elements);
- snd_iprintf(buffer, "%sCells in use : %d\n", space, atomic_read(&pool->counter));
- snd_iprintf(buffer, "%sPeak cells in use : %d\n", space, pool->max_used);
- snd_iprintf(buffer, "%sAlloc success : %d\n", space, pool->event_alloc_success);
- snd_iprintf(buffer, "%sAlloc failures : %d\n", space, pool->event_alloc_failures);
-}
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_memory.h b/ANDROID_3.4.5/sound/core/seq/seq_memory.h
deleted file mode 100644
index 4a2ec779..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_memory.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * ALSA sequencer Memory Manager
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __SND_SEQ_MEMORYMGR_H
-#define __SND_SEQ_MEMORYMGR_H
-
-#include <sound/seq_kernel.h>
-#include <linux/poll.h>
-
-struct snd_info_buffer;
-
-/* container for sequencer event (internal use) */
-struct snd_seq_event_cell {
- struct snd_seq_event event;
- struct snd_seq_pool *pool; /* used pool */
- struct snd_seq_event_cell *next; /* next cell */
-};
-
-/* design note: the pool is a contiguous block of memory, if we dynamicly
- want to add additional cells to the pool be better store this in another
- pool as we need to know the base address of the pool when releasing
- memory. */
-
-struct snd_seq_pool {
- struct snd_seq_event_cell *ptr; /* pointer to first event chunk */
- struct snd_seq_event_cell *free; /* pointer to the head of the free list */
-
- int total_elements; /* pool size actually allocated */
- atomic_t counter; /* cells free */
-
- int size; /* pool size to be allocated */
- int room; /* watermark for sleep/wakeup */
-
- int closing;
-
- /* statistics */
- int max_used;
- int event_alloc_nopool;
- int event_alloc_failures;
- int event_alloc_success;
-
- /* Write locking */
- wait_queue_head_t output_sleep;
-
- /* Pool lock */
- spinlock_t lock;
-};
-
-void snd_seq_cell_free(struct snd_seq_event_cell *cell);
-
-int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
- struct snd_seq_event_cell **cellp, int nonblock, struct file *file);
-
-/* return number of unused (free) cells */
-static inline int snd_seq_unused_cells(struct snd_seq_pool *pool)
-{
- return pool ? pool->total_elements - atomic_read(&pool->counter) : 0;
-}
-
-/* return total number of allocated cells */
-static inline int snd_seq_total_cells(struct snd_seq_pool *pool)
-{
- return pool ? pool->total_elements : 0;
-}
-
-/* init pool - allocate events */
-int snd_seq_pool_init(struct snd_seq_pool *pool);
-
-/* done pool - free events */
-int snd_seq_pool_done(struct snd_seq_pool *pool);
-
-/* create pool */
-struct snd_seq_pool *snd_seq_pool_new(int poolsize);
-
-/* remove pool */
-int snd_seq_pool_delete(struct snd_seq_pool **pool);
-
-/* init memory */
-int snd_sequencer_memory_init(void);
-
-/* release event memory */
-void snd_sequencer_memory_done(void);
-
-/* polling */
-int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait);
-
-void snd_seq_info_pool(struct snd_info_buffer *buffer,
- struct snd_seq_pool *pool, char *space);
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_midi.c b/ANDROID_3.4.5/sound/core/seq/seq_midi.c
deleted file mode 100644
index 64069dbf..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_midi.c
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Generic MIDI synth driver for ALSA sequencer
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@perex.cz>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/*
-Possible options for midisynth module:
- - automatic opening of midi ports on first received event or subscription
- (close will be performed when client leaves)
-*/
-
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <sound/core.h>
-#include <sound/rawmidi.h>
-#include <sound/seq_kernel.h>
-#include <sound/seq_device.h>
-#include <sound/seq_midi_event.h>
-#include <sound/initval.h>
-
-MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth.");
-MODULE_LICENSE("GPL");
-static int output_buffer_size = PAGE_SIZE;
-module_param(output_buffer_size, int, 0644);
-MODULE_PARM_DESC(output_buffer_size, "Output buffer size in bytes.");
-static int input_buffer_size = PAGE_SIZE;
-module_param(input_buffer_size, int, 0644);
-MODULE_PARM_DESC(input_buffer_size, "Input buffer size in bytes.");
-
-/* data for this midi synth driver */
-struct seq_midisynth {
- struct snd_card *card;
- int device;
- int subdevice;
- struct snd_rawmidi_file input_rfile;
- struct snd_rawmidi_file output_rfile;
- int seq_client;
- int seq_port;
- struct snd_midi_event *parser;
-};
-
-struct seq_midisynth_client {
- int seq_client;
- int num_ports;
- int ports_per_device[SNDRV_RAWMIDI_DEVICES];
- struct seq_midisynth *ports[SNDRV_RAWMIDI_DEVICES];
-};
-
-static struct seq_midisynth_client *synths[SNDRV_CARDS];
-static DEFINE_MUTEX(register_mutex);
-
-/* handle rawmidi input event (MIDI v1.0 stream) */
-static void snd_midi_input_event(struct snd_rawmidi_substream *substream)
-{
- struct snd_rawmidi_runtime *runtime;
- struct seq_midisynth *msynth;
- struct snd_seq_event ev;
- char buf[16], *pbuf;
- long res, count;
-
- if (substream == NULL)
- return;
- runtime = substream->runtime;
- msynth = runtime->private_data;
- if (msynth == NULL)
- return;
- memset(&ev, 0, sizeof(ev));
- while (runtime->avail > 0) {
- res = snd_rawmidi_kernel_read(substream, buf, sizeof(buf));
- if (res <= 0)
- continue;
- if (msynth->parser == NULL)
- continue;
- pbuf = buf;
- while (res > 0) {
- count = snd_midi_event_encode(msynth->parser, pbuf, res, &ev);
- if (count < 0)
- break;
- pbuf += count;
- res -= count;
- if (ev.type != SNDRV_SEQ_EVENT_NONE) {
- ev.source.port = msynth->seq_port;
- ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0);
- /* clear event and reset header */
- memset(&ev, 0, sizeof(ev));
- }
- }
- }
-}
-
-static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, int count)
-{
- struct snd_rawmidi_runtime *runtime;
- int tmp;
-
- if (snd_BUG_ON(!substream || !buf))
- return -EINVAL;
- runtime = substream->runtime;
- if ((tmp = runtime->avail) < count) {
- if (printk_ratelimit())
- snd_printk(KERN_ERR "MIDI output buffer overrun\n");
- return -ENOMEM;
- }
- if (snd_rawmidi_kernel_write(substream, buf, count) < count)
- return -EINVAL;
- return 0;
-}
-
-static int event_process_midi(struct snd_seq_event *ev, int direct,
- void *private_data, int atomic, int hop)
-{
- struct seq_midisynth *msynth = private_data;
- unsigned char msg[10]; /* buffer for constructing midi messages */
- struct snd_rawmidi_substream *substream;
- int len;
-
- if (snd_BUG_ON(!msynth))
- return -EINVAL;
- substream = msynth->output_rfile.output;
- if (substream == NULL)
- return -ENODEV;
- if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { /* special case, to save space */
- if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) {
- /* invalid event */
- snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags);
- return 0;
- }
- snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream);
- snd_midi_event_reset_decode(msynth->parser);
- } else {
- if (msynth->parser == NULL)
- return -EIO;
- len = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev);
- if (len < 0)
- return 0;
- if (dump_midi(substream, msg, len) < 0)
- snd_midi_event_reset_decode(msynth->parser);
- }
- return 0;
-}
-
-
-static int snd_seq_midisynth_new(struct seq_midisynth *msynth,
- struct snd_card *card,
- int device,
- int subdevice)
-{
- if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &msynth->parser) < 0)
- return -ENOMEM;
- msynth->card = card;
- msynth->device = device;
- msynth->subdevice = subdevice;
- return 0;
-}
-
-/* open associated midi device for input */
-static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe *info)
-{
- int err;
- struct seq_midisynth *msynth = private_data;
- struct snd_rawmidi_runtime *runtime;
- struct snd_rawmidi_params params;
-
- /* open midi port */
- if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
- msynth->subdevice,
- SNDRV_RAWMIDI_LFLG_INPUT,
- &msynth->input_rfile)) < 0) {
- snd_printd("midi input open failed!!!\n");
- return err;
- }
- runtime = msynth->input_rfile.input->runtime;
- memset(&params, 0, sizeof(params));
- params.avail_min = 1;
- params.buffer_size = input_buffer_size;
- if ((err = snd_rawmidi_input_params(msynth->input_rfile.input, &params)) < 0) {
- snd_rawmidi_kernel_release(&msynth->input_rfile);
- return err;
- }
- snd_midi_event_reset_encode(msynth->parser);
- runtime->event = snd_midi_input_event;
- runtime->private_data = msynth;
- snd_rawmidi_kernel_read(msynth->input_rfile.input, NULL, 0);
- return 0;
-}
-
-/* close associated midi device for input */
-static int midisynth_unsubscribe(void *private_data, struct snd_seq_port_subscribe *info)
-{
- int err;
- struct seq_midisynth *msynth = private_data;
-
- if (snd_BUG_ON(!msynth->input_rfile.input))
- return -EINVAL;
- err = snd_rawmidi_kernel_release(&msynth->input_rfile);
- return err;
-}
-
-/* open associated midi device for output */
-static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info)
-{
- int err;
- struct seq_midisynth *msynth = private_data;
- struct snd_rawmidi_params params;
-
- /* open midi port */
- if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
- msynth->subdevice,
- SNDRV_RAWMIDI_LFLG_OUTPUT,
- &msynth->output_rfile)) < 0) {
- snd_printd("midi output open failed!!!\n");
- return err;
- }
- memset(&params, 0, sizeof(params));
- params.avail_min = 1;
- params.buffer_size = output_buffer_size;
- params.no_active_sensing = 1;
- if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, &params)) < 0) {
- snd_rawmidi_kernel_release(&msynth->output_rfile);
- return err;
- }
- snd_midi_event_reset_decode(msynth->parser);
- return 0;
-}
-
-/* close associated midi device for output */
-static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info)
-{
- struct seq_midisynth *msynth = private_data;
-
- if (snd_BUG_ON(!msynth->output_rfile.output))
- return -EINVAL;
- snd_rawmidi_drain_output(msynth->output_rfile.output);
- return snd_rawmidi_kernel_release(&msynth->output_rfile);
-}
-
-/* delete given midi synth port */
-static void snd_seq_midisynth_delete(struct seq_midisynth *msynth)
-{
- if (msynth == NULL)
- return;
-
- if (msynth->seq_client > 0) {
- /* delete port */
- snd_seq_event_port_detach(msynth->seq_client, msynth->seq_port);
- }
-
- if (msynth->parser)
- snd_midi_event_free(msynth->parser);
-}
-
-/* register new midi synth port */
-static int
-snd_seq_midisynth_register_port(struct snd_seq_device *dev)
-{
- struct seq_midisynth_client *client;
- struct seq_midisynth *msynth, *ms;
- struct snd_seq_port_info *port;
- struct snd_rawmidi_info *info;
- struct snd_rawmidi *rmidi = dev->private_data;
- int newclient = 0;
- unsigned int p, ports;
- struct snd_seq_port_callback pcallbacks;
- struct snd_card *card = dev->card;
- int device = dev->device;
- unsigned int input_count = 0, output_count = 0;
-
- if (snd_BUG_ON(!card || device < 0 || device >= SNDRV_RAWMIDI_DEVICES))
- return -EINVAL;
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info)
- return -ENOMEM;
- info->device = device;
- info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
- info->subdevice = 0;
- if (snd_rawmidi_info_select(card, info) >= 0)
- output_count = info->subdevices_count;
- info->stream = SNDRV_RAWMIDI_STREAM_INPUT;
- if (snd_rawmidi_info_select(card, info) >= 0) {
- input_count = info->subdevices_count;
- }
- ports = output_count;
- if (ports < input_count)
- ports = input_count;
- if (ports == 0) {
- kfree(info);
- return -ENODEV;
- }
- if (ports > (256 / SNDRV_RAWMIDI_DEVICES))
- ports = 256 / SNDRV_RAWMIDI_DEVICES;
-
- mutex_lock(&register_mutex);
- client = synths[card->number];
- if (client == NULL) {
- newclient = 1;
- client = kzalloc(sizeof(*client), GFP_KERNEL);
- if (client == NULL) {
- mutex_unlock(&register_mutex);
- kfree(info);
- return -ENOMEM;
- }
- client->seq_client =
- snd_seq_create_kernel_client(
- card, 0, "%s", card->shortname[0] ?
- (const char *)card->shortname : "External MIDI");
- if (client->seq_client < 0) {
- kfree(client);
- mutex_unlock(&register_mutex);
- kfree(info);
- return -ENOMEM;
- }
- }
-
- msynth = kcalloc(ports, sizeof(struct seq_midisynth), GFP_KERNEL);
- port = kmalloc(sizeof(*port), GFP_KERNEL);
- if (msynth == NULL || port == NULL)
- goto __nomem;
-
- for (p = 0; p < ports; p++) {
- ms = &msynth[p];
-
- if (snd_seq_midisynth_new(ms, card, device, p) < 0)
- goto __nomem;
-
- /* declare port */
- memset(port, 0, sizeof(*port));
- port->addr.client = client->seq_client;
- port->addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p;
- port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
- memset(info, 0, sizeof(*info));
- info->device = device;
- if (p < output_count)
- info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
- else
- info->stream = SNDRV_RAWMIDI_STREAM_INPUT;
- info->subdevice = p;
- if (snd_rawmidi_info_select(card, info) >= 0)
- strcpy(port->name, info->subname);
- if (! port->name[0]) {
- if (info->name[0]) {
- if (ports > 1)
- snprintf(port->name, sizeof(port->name), "%s-%d", info->name, p);
- else
- snprintf(port->name, sizeof(port->name), "%s", info->name);
- } else {
- /* last resort */
- if (ports > 1)
- sprintf(port->name, "MIDI %d-%d-%d", card->number, device, p);
- else
- sprintf(port->name, "MIDI %d-%d", card->number, device);
- }
- }
- if ((info->flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count)
- port->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
- if ((info->flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count)
- port->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
- if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) &&
- info->flags & SNDRV_RAWMIDI_INFO_DUPLEX)
- port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
- port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
- | SNDRV_SEQ_PORT_TYPE_HARDWARE
- | SNDRV_SEQ_PORT_TYPE_PORT;
- port->midi_channels = 16;
- memset(&pcallbacks, 0, sizeof(pcallbacks));
- pcallbacks.owner = THIS_MODULE;
- pcallbacks.private_data = ms;
- pcallbacks.subscribe = midisynth_subscribe;
- pcallbacks.unsubscribe = midisynth_unsubscribe;
- pcallbacks.use = midisynth_use;
- pcallbacks.unuse = midisynth_unuse;
- pcallbacks.event_input = event_process_midi;
- port->kernel = &pcallbacks;
- if (rmidi->ops && rmidi->ops->get_port_info)
- rmidi->ops->get_port_info(rmidi, p, port);
- if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0)
- goto __nomem;
- ms->seq_client = client->seq_client;
- ms->seq_port = port->addr.port;
- }
- client->ports_per_device[device] = ports;
- client->ports[device] = msynth;
- client->num_ports++;
- if (newclient)
- synths[card->number] = client;
- mutex_unlock(&register_mutex);
- kfree(info);
- kfree(port);
- return 0; /* success */
-
- __nomem:
- if (msynth != NULL) {
- for (p = 0; p < ports; p++)
- snd_seq_midisynth_delete(&msynth[p]);
- kfree(msynth);
- }
- if (newclient) {
- snd_seq_delete_kernel_client(client->seq_client);
- kfree(client);
- }
- kfree(info);
- kfree(port);
- mutex_unlock(&register_mutex);
- return -ENOMEM;
-}
-
-/* release midi synth port */
-static int
-snd_seq_midisynth_unregister_port(struct snd_seq_device *dev)
-{
- struct seq_midisynth_client *client;
- struct seq_midisynth *msynth;
- struct snd_card *card = dev->card;
- int device = dev->device, p, ports;
-
- mutex_lock(&register_mutex);
- client = synths[card->number];
- if (client == NULL || client->ports[device] == NULL) {
- mutex_unlock(&register_mutex);
- return -ENODEV;
- }
- ports = client->ports_per_device[device];
- client->ports_per_device[device] = 0;
- msynth = client->ports[device];
- client->ports[device] = NULL;
- for (p = 0; p < ports; p++)
- snd_seq_midisynth_delete(&msynth[p]);
- kfree(msynth);
- client->num_ports--;
- if (client->num_ports <= 0) {
- snd_seq_delete_kernel_client(client->seq_client);
- synths[card->number] = NULL;
- kfree(client);
- }
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-
-static int __init alsa_seq_midi_init(void)
-{
- static struct snd_seq_dev_ops ops = {
- snd_seq_midisynth_register_port,
- snd_seq_midisynth_unregister_port,
- };
- memset(&synths, 0, sizeof(synths));
- snd_seq_autoload_lock();
- snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH, &ops, 0);
- snd_seq_autoload_unlock();
- return 0;
-}
-
-static void __exit alsa_seq_midi_exit(void)
-{
- snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH);
-}
-
-module_init(alsa_seq_midi_init)
-module_exit(alsa_seq_midi_exit)
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_midi_emul.c b/ANDROID_3.4.5/sound/core/seq/seq_midi_emul.c
deleted file mode 100644
index 6f64471d..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_midi_emul.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * GM/GS/XG midi module.
- *
- * Copyright (C) 1999 Steve Ratcliffe
- *
- * Based on awe_wave.c by Takashi Iwai
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-/*
- * This module is used to keep track of the current midi state.
- * It can be used for drivers that are required to emulate midi when
- * the hardware doesn't.
- *
- * It was written for a AWE64 driver, but there should be no AWE specific
- * code in here. If there is it should be reported as a bug.
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/seq_kernel.h>
-#include <sound/seq_midi_emul.h>
-#include <sound/initval.h>
-#include <sound/asoundef.h>
-
-MODULE_AUTHOR("Takashi Iwai / Steve Ratcliffe");
-MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation.");
-MODULE_LICENSE("GPL");
-
-/* Prototypes for static functions */
-static void note_off(struct snd_midi_op *ops, void *drv,
- struct snd_midi_channel *chan,
- int note, int vel);
-static void do_control(struct snd_midi_op *ops, void *private,
- struct snd_midi_channel_set *chset,
- struct snd_midi_channel *chan,
- int control, int value);
-static void rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
- struct snd_midi_channel_set *chset);
-static void nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
- struct snd_midi_channel_set *chset);
-static void sysex(struct snd_midi_op *ops, void *private, unsigned char *sysex,
- int len, struct snd_midi_channel_set *chset);
-static void all_sounds_off(struct snd_midi_op *ops, void *private,
- struct snd_midi_channel *chan);
-static void all_notes_off(struct snd_midi_op *ops, void *private,
- struct snd_midi_channel *chan);
-static void snd_midi_reset_controllers(struct snd_midi_channel *chan);
-static void reset_all_channels(struct snd_midi_channel_set *chset);
-
-
-/*
- * Process an event in a driver independent way. This means dealing
- * with RPN, NRPN, SysEx etc that are defined for common midi applications
- * such as GM, GS and XG.
- * There modes that this module will run in are:
- * Generic MIDI - no interpretation at all, it will just save current values
- * of controllers etc.
- * GM - You can use all gm_ prefixed elements of chan. Controls, RPN, NRPN,
- * SysEx will be interpreded as defined in General Midi.
- * GS - You can use all gs_ prefixed elements of chan. Codes for GS will be
- * interpreted.
- * XG - You can use all xg_ prefixed elements of chan. Codes for XG will
- * be interpreted.
- */
-void
-snd_midi_process_event(struct snd_midi_op *ops,
- struct snd_seq_event *ev,
- struct snd_midi_channel_set *chanset)
-{
- struct snd_midi_channel *chan;
- void *drv;
- int dest_channel = 0;
-
- if (ev == NULL || chanset == NULL) {
- snd_printd("ev or chanbase NULL (snd_midi_process_event)\n");
- return;
- }
- if (chanset->channels == NULL)
- return;
-
- if (snd_seq_ev_is_channel_type(ev)) {
- dest_channel = ev->data.note.channel;
- if (dest_channel >= chanset->max_channels) {
- snd_printd("dest channel is %d, max is %d\n",
- dest_channel, chanset->max_channels);
- return;
- }
- }
-
- chan = chanset->channels + dest_channel;
- drv = chanset->private_data;
-
- /* EVENT_NOTE should be processed before queued */
- if (ev->type == SNDRV_SEQ_EVENT_NOTE)
- return;
-
- /* Make sure that we don't have a note on that should really be
- * a note off */
- if (ev->type == SNDRV_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0)
- ev->type = SNDRV_SEQ_EVENT_NOTEOFF;
-
- /* Make sure the note is within array range */
- if (ev->type == SNDRV_SEQ_EVENT_NOTEON ||
- ev->type == SNDRV_SEQ_EVENT_NOTEOFF ||
- ev->type == SNDRV_SEQ_EVENT_KEYPRESS) {
- if (ev->data.note.note >= 128)
- return;
- }
-
- switch (ev->type) {
- case SNDRV_SEQ_EVENT_NOTEON:
- if (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON) {
- if (ops->note_off)
- ops->note_off(drv, ev->data.note.note, 0, chan);
- }
- chan->note[ev->data.note.note] = SNDRV_MIDI_NOTE_ON;
- if (ops->note_on)
- ops->note_on(drv, ev->data.note.note, ev->data.note.velocity, chan);
- break;
- case SNDRV_SEQ_EVENT_NOTEOFF:
- if (! (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON))
- break;
- if (ops->note_off)
- note_off(ops, drv, chan, ev->data.note.note, ev->data.note.velocity);
- break;
- case SNDRV_SEQ_EVENT_KEYPRESS:
- if (ops->key_press)
- ops->key_press(drv, ev->data.note.note, ev->data.note.velocity, chan);
- break;
- case SNDRV_SEQ_EVENT_CONTROLLER:
- do_control(ops, drv, chanset, chan,
- ev->data.control.param, ev->data.control.value);
- break;
- case SNDRV_SEQ_EVENT_PGMCHANGE:
- chan->midi_program = ev->data.control.value;
- break;
- case SNDRV_SEQ_EVENT_PITCHBEND:
- chan->midi_pitchbend = ev->data.control.value;
- if (ops->control)
- ops->control(drv, MIDI_CTL_PITCHBEND, chan);
- break;
- case SNDRV_SEQ_EVENT_CHANPRESS:
- chan->midi_pressure = ev->data.control.value;
- if (ops->control)
- ops->control(drv, MIDI_CTL_CHAN_PRESSURE, chan);
- break;
- case SNDRV_SEQ_EVENT_CONTROL14:
- /* Best guess is that this is any of the 14 bit controller values */
- if (ev->data.control.param < 32) {
- /* set low part first */
- chan->control[ev->data.control.param + 32] =
- ev->data.control.value & 0x7f;
- do_control(ops, drv, chanset, chan,
- ev->data.control.param,
- ((ev->data.control.value>>7) & 0x7f));
- } else
- do_control(ops, drv, chanset, chan,
- ev->data.control.param,
- ev->data.control.value);
- break;
- case SNDRV_SEQ_EVENT_NONREGPARAM:
- /* Break it back into its controller values */
- chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED;
- chan->control[MIDI_CTL_MSB_DATA_ENTRY]
- = (ev->data.control.value >> 7) & 0x7f;
- chan->control[MIDI_CTL_LSB_DATA_ENTRY]
- = ev->data.control.value & 0x7f;
- chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB]
- = (ev->data.control.param >> 7) & 0x7f;
- chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB]
- = ev->data.control.param & 0x7f;
- nrpn(ops, drv, chan, chanset);
- break;
- case SNDRV_SEQ_EVENT_REGPARAM:
- /* Break it back into its controller values */
- chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED;
- chan->control[MIDI_CTL_MSB_DATA_ENTRY]
- = (ev->data.control.value >> 7) & 0x7f;
- chan->control[MIDI_CTL_LSB_DATA_ENTRY]
- = ev->data.control.value & 0x7f;
- chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB]
- = (ev->data.control.param >> 7) & 0x7f;
- chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB]
- = ev->data.control.param & 0x7f;
- rpn(ops, drv, chan, chanset);
- break;
- case SNDRV_SEQ_EVENT_SYSEX:
- if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE) {
- unsigned char sysexbuf[64];
- int len;
- len = snd_seq_expand_var_event(ev, sizeof(sysexbuf), sysexbuf, 1, 0);
- if (len > 0)
- sysex(ops, drv, sysexbuf, len, chanset);
- }
- break;
- case SNDRV_SEQ_EVENT_SONGPOS:
- case SNDRV_SEQ_EVENT_SONGSEL:
- case SNDRV_SEQ_EVENT_CLOCK:
- case SNDRV_SEQ_EVENT_START:
- case SNDRV_SEQ_EVENT_CONTINUE:
- case SNDRV_SEQ_EVENT_STOP:
- case SNDRV_SEQ_EVENT_QFRAME:
- case SNDRV_SEQ_EVENT_TEMPO:
- case SNDRV_SEQ_EVENT_TIMESIGN:
- case SNDRV_SEQ_EVENT_KEYSIGN:
- goto not_yet;
- case SNDRV_SEQ_EVENT_SENSING:
- break;
- case SNDRV_SEQ_EVENT_CLIENT_START:
- case SNDRV_SEQ_EVENT_CLIENT_EXIT:
- case SNDRV_SEQ_EVENT_CLIENT_CHANGE:
- case SNDRV_SEQ_EVENT_PORT_START:
- case SNDRV_SEQ_EVENT_PORT_EXIT:
- case SNDRV_SEQ_EVENT_PORT_CHANGE:
- case SNDRV_SEQ_EVENT_ECHO:
- not_yet:
- default:
- /*snd_printd("Unimplemented event %d\n", ev->type);*/
- break;
- }
-}
-
-
-/*
- * release note
- */
-static void
-note_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
- int note, int vel)
-{
- if (chan->gm_hold) {
- /* Hold this note until pedal is turned off */
- chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
- } else if (chan->note[note] & SNDRV_MIDI_NOTE_SOSTENUTO) {
- /* Mark this note as release; it will be turned off when sostenuto
- * is turned off */
- chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
- } else {
- chan->note[note] = 0;
- if (ops->note_off)
- ops->note_off(drv, note, vel, chan);
- }
-}
-
-/*
- * Do all driver independent operations for this controller and pass
- * events that need to take place immediately to the driver.
- */
-static void
-do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chset,
- struct snd_midi_channel *chan, int control, int value)
-{
- int i;
-
- /* Switches */
- if ((control >=64 && control <=69) || (control >= 80 && control <= 83)) {
- /* These are all switches; either off or on so set to 0 or 127 */
- value = (value >= 64)? 127: 0;
- }
- chan->control[control] = value;
-
- switch (control) {
- case MIDI_CTL_SUSTAIN:
- if (value == 0) {
- /* Sustain has been released, turn off held notes */
- for (i = 0; i < 128; i++) {
- if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) {
- chan->note[i] = SNDRV_MIDI_NOTE_OFF;
- if (ops->note_off)
- ops->note_off(drv, i, 0, chan);
- }
- }
- }
- break;
- case MIDI_CTL_PORTAMENTO:
- break;
- case MIDI_CTL_SOSTENUTO:
- if (value) {
- /* Mark each note that is currently held down */
- for (i = 0; i < 128; i++) {
- if (chan->note[i] & SNDRV_MIDI_NOTE_ON)
- chan->note[i] |= SNDRV_MIDI_NOTE_SOSTENUTO;
- }
- } else {
- /* release all notes that were held */
- for (i = 0; i < 128; i++) {
- if (chan->note[i] & SNDRV_MIDI_NOTE_SOSTENUTO) {
- chan->note[i] &= ~SNDRV_MIDI_NOTE_SOSTENUTO;
- if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) {
- chan->note[i] = SNDRV_MIDI_NOTE_OFF;
- if (ops->note_off)
- ops->note_off(drv, i, 0, chan);
- }
- }
- }
- }
- break;
- case MIDI_CTL_MSB_DATA_ENTRY:
- chan->control[MIDI_CTL_LSB_DATA_ENTRY] = 0;
- /* go through here */
- case MIDI_CTL_LSB_DATA_ENTRY:
- if (chan->param_type == SNDRV_MIDI_PARAM_TYPE_REGISTERED)
- rpn(ops, drv, chan, chset);
- else
- nrpn(ops, drv, chan, chset);
- break;
- case MIDI_CTL_REGIST_PARM_NUM_LSB:
- case MIDI_CTL_REGIST_PARM_NUM_MSB:
- chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED;
- break;
- case MIDI_CTL_NONREG_PARM_NUM_LSB:
- case MIDI_CTL_NONREG_PARM_NUM_MSB:
- chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED;
- break;
-
- case MIDI_CTL_ALL_SOUNDS_OFF:
- all_sounds_off(ops, drv, chan);
- break;
-
- case MIDI_CTL_ALL_NOTES_OFF:
- all_notes_off(ops, drv, chan);
- break;
-
- case MIDI_CTL_MSB_BANK:
- if (chset->midi_mode == SNDRV_MIDI_MODE_XG) {
- if (value == 127)
- chan->drum_channel = 1;
- else
- chan->drum_channel = 0;
- }
- break;
- case MIDI_CTL_LSB_BANK:
- break;
-
- case MIDI_CTL_RESET_CONTROLLERS:
- snd_midi_reset_controllers(chan);
- break;
-
- case MIDI_CTL_SOFT_PEDAL:
- case MIDI_CTL_LEGATO_FOOTSWITCH:
- case MIDI_CTL_HOLD2:
- case MIDI_CTL_SC1_SOUND_VARIATION:
- case MIDI_CTL_SC2_TIMBRE:
- case MIDI_CTL_SC3_RELEASE_TIME:
- case MIDI_CTL_SC4_ATTACK_TIME:
- case MIDI_CTL_SC5_BRIGHTNESS:
- case MIDI_CTL_E1_REVERB_DEPTH:
- case MIDI_CTL_E2_TREMOLO_DEPTH:
- case MIDI_CTL_E3_CHORUS_DEPTH:
- case MIDI_CTL_E4_DETUNE_DEPTH:
- case MIDI_CTL_E5_PHASER_DEPTH:
- goto notyet;
- notyet:
- default:
- if (ops->control)
- ops->control(drv, control, chan);
- break;
- }
-}
-
-
-/*
- * initialize the MIDI status
- */
-void
-snd_midi_channel_set_clear(struct snd_midi_channel_set *chset)
-{
- int i;
-
- chset->midi_mode = SNDRV_MIDI_MODE_GM;
- chset->gs_master_volume = 127;
-
- for (i = 0; i < chset->max_channels; i++) {
- struct snd_midi_channel *chan = chset->channels + i;
- memset(chan->note, 0, sizeof(chan->note));
-
- chan->midi_aftertouch = 0;
- chan->midi_pressure = 0;
- chan->midi_program = 0;
- chan->midi_pitchbend = 0;
- snd_midi_reset_controllers(chan);
- chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */
- chan->gm_rpn_fine_tuning = 0;
- chan->gm_rpn_coarse_tuning = 0;
-
- if (i == 9)
- chan->drum_channel = 1;
- else
- chan->drum_channel = 0;
- }
-}
-
-/*
- * Process a rpn message.
- */
-static void
-rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
- struct snd_midi_channel_set *chset)
-{
- int type;
- int val;
-
- if (chset->midi_mode != SNDRV_MIDI_MODE_NONE) {
- type = (chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB] << 8) |
- chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB];
- val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) |
- chan->control[MIDI_CTL_LSB_DATA_ENTRY];
-
- switch (type) {
- case 0x0000: /* Pitch bend sensitivity */
- /* MSB only / 1 semitone per 128 */
- chan->gm_rpn_pitch_bend_range = val;
- break;
-
- case 0x0001: /* fine tuning: */
- /* MSB/LSB, 8192=center, 100/8192 cent step */
- chan->gm_rpn_fine_tuning = val - 8192;
- break;
-
- case 0x0002: /* coarse tuning */
- /* MSB only / 8192=center, 1 semitone per 128 */
- chan->gm_rpn_coarse_tuning = val - 8192;
- break;
-
- case 0x7F7F: /* "lock-in" RPN */
- /* ignored */
- break;
- }
- }
- /* should call nrpn or rpn callback here.. */
-}
-
-/*
- * Process an nrpn message.
- */
-static void
-nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
- struct snd_midi_channel_set *chset)
-{
- /* parse XG NRPNs here if possible */
- if (ops->nrpn)
- ops->nrpn(drv, chan, chset);
-}
-
-
-/*
- * convert channel parameter in GS sysex
- */
-static int
-get_channel(unsigned char cmd)
-{
- int p = cmd & 0x0f;
- if (p == 0)
- p = 9;
- else if (p < 10)
- p--;
- return p;
-}
-
-
-/*
- * Process a sysex message.
- */
-static void
-sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
- struct snd_midi_channel_set *chset)
-{
- /* GM on */
- static unsigned char gm_on_macro[] = {
- 0x7e,0x7f,0x09,0x01,
- };
- /* XG on */
- static unsigned char xg_on_macro[] = {
- 0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,
- };
- /* GS prefix
- * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off
- * reverb mode: XX=0x01, YY=0x30, ZZ=0-7
- * chorus mode: XX=0x01, YY=0x38, ZZ=0-7
- * master vol: XX=0x00, YY=0x04, ZZ=0-127
- */
- static unsigned char gs_pfx_macro[] = {
- 0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/
- };
-
- int parsed = SNDRV_MIDI_SYSEX_NOT_PARSED;
-
- if (len <= 0 || buf[0] != 0xf0)
- return;
- /* skip first byte */
- buf++;
- len--;
-
- /* GM on */
- if (len >= (int)sizeof(gm_on_macro) &&
- memcmp(buf, gm_on_macro, sizeof(gm_on_macro)) == 0) {
- if (chset->midi_mode != SNDRV_MIDI_MODE_GS &&
- chset->midi_mode != SNDRV_MIDI_MODE_XG) {
- chset->midi_mode = SNDRV_MIDI_MODE_GM;
- reset_all_channels(chset);
- parsed = SNDRV_MIDI_SYSEX_GM_ON;
- }
- }
-
- /* GS macros */
- else if (len >= 8 &&
- memcmp(buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) {
- if (chset->midi_mode != SNDRV_MIDI_MODE_GS &&
- chset->midi_mode != SNDRV_MIDI_MODE_XG)
- chset->midi_mode = SNDRV_MIDI_MODE_GS;
-
- if (buf[5] == 0x00 && buf[6] == 0x7f && buf[7] == 0x00) {
- /* GS reset */
- parsed = SNDRV_MIDI_SYSEX_GS_RESET;
- reset_all_channels(chset);
- }
-
- else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x15) {
- /* drum pattern */
- int p = get_channel(buf[5]);
- if (p < chset->max_channels) {
- parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL;
- if (buf[7])
- chset->channels[p].drum_channel = 1;
- else
- chset->channels[p].drum_channel = 0;
- }
-
- } else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x21) {
- /* program */
- int p = get_channel(buf[5]);
- if (p < chset->max_channels &&
- ! chset->channels[p].drum_channel) {
- parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL;
- chset->channels[p].midi_program = buf[7];
- }
-
- } else if (buf[5] == 0x01 && buf[6] == 0x30) {
- /* reverb mode */
- parsed = SNDRV_MIDI_SYSEX_GS_REVERB_MODE;
- chset->gs_reverb_mode = buf[7];
-
- } else if (buf[5] == 0x01 && buf[6] == 0x38) {
- /* chorus mode */
- parsed = SNDRV_MIDI_SYSEX_GS_CHORUS_MODE;
- chset->gs_chorus_mode = buf[7];
-
- } else if (buf[5] == 0x00 && buf[6] == 0x04) {
- /* master volume */
- parsed = SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME;
- chset->gs_master_volume = buf[7];
-
- }
- }
-
- /* XG on */
- else if (len >= (int)sizeof(xg_on_macro) &&
- memcmp(buf, xg_on_macro, sizeof(xg_on_macro)) == 0) {
- int i;
- chset->midi_mode = SNDRV_MIDI_MODE_XG;
- parsed = SNDRV_MIDI_SYSEX_XG_ON;
- /* reset CC#0 for drums */
- for (i = 0; i < chset->max_channels; i++) {
- if (chset->channels[i].drum_channel)
- chset->channels[i].control[MIDI_CTL_MSB_BANK] = 127;
- else
- chset->channels[i].control[MIDI_CTL_MSB_BANK] = 0;
- }
- }
-
- if (ops->sysex)
- ops->sysex(private, buf - 1, len + 1, parsed, chset);
-}
-
-/*
- * all sound off
- */
-static void
-all_sounds_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan)
-{
- int n;
-
- if (! ops->note_terminate)
- return;
- for (n = 0; n < 128; n++) {
- if (chan->note[n]) {
- ops->note_terminate(drv, n, chan);
- chan->note[n] = 0;
- }
- }
-}
-
-/*
- * all notes off
- */
-static void
-all_notes_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan)
-{
- int n;
-
- if (! ops->note_off)
- return;
- for (n = 0; n < 128; n++) {
- if (chan->note[n] == SNDRV_MIDI_NOTE_ON)
- note_off(ops, drv, chan, n, 0);
- }
-}
-
-/*
- * Initialise a single midi channel control block.
- */
-static void snd_midi_channel_init(struct snd_midi_channel *p, int n)
-{
- if (p == NULL)
- return;
-
- memset(p, 0, sizeof(struct snd_midi_channel));
- p->private = NULL;
- p->number = n;
-
- snd_midi_reset_controllers(p);
- p->gm_rpn_pitch_bend_range = 256; /* 2 semitones */
- p->gm_rpn_fine_tuning = 0;
- p->gm_rpn_coarse_tuning = 0;
-
- if (n == 9)
- p->drum_channel = 1; /* Default ch 10 as drums */
-}
-
-/*
- * Allocate and initialise a set of midi channel control blocks.
- */
-static struct snd_midi_channel *snd_midi_channel_init_set(int n)
-{
- struct snd_midi_channel *chan;
- int i;
-
- chan = kmalloc(n * sizeof(struct snd_midi_channel), GFP_KERNEL);
- if (chan) {
- for (i = 0; i < n; i++)
- snd_midi_channel_init(chan+i, i);
- }
-
- return chan;
-}
-
-/*
- * reset all midi channels
- */
-static void
-reset_all_channels(struct snd_midi_channel_set *chset)
-{
- int ch;
- for (ch = 0; ch < chset->max_channels; ch++) {
- struct snd_midi_channel *chan = chset->channels + ch;
- snd_midi_reset_controllers(chan);
- chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */
- chan->gm_rpn_fine_tuning = 0;
- chan->gm_rpn_coarse_tuning = 0;
-
- if (ch == 9)
- chan->drum_channel = 1;
- else
- chan->drum_channel = 0;
- }
-}
-
-
-/*
- * Allocate and initialise a midi channel set.
- */
-struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n)
-{
- struct snd_midi_channel_set *chset;
-
- chset = kmalloc(sizeof(*chset), GFP_KERNEL);
- if (chset) {
- chset->channels = snd_midi_channel_init_set(n);
- chset->private_data = NULL;
- chset->max_channels = n;
- }
- return chset;
-}
-
-/*
- * Reset the midi controllers on a particular channel to default values.
- */
-static void snd_midi_reset_controllers(struct snd_midi_channel *chan)
-{
- memset(chan->control, 0, sizeof(chan->control));
- chan->gm_volume = 127;
- chan->gm_expression = 127;
- chan->gm_pan = 64;
-}
-
-
-/*
- * Free a midi channel set.
- */
-void snd_midi_channel_free_set(struct snd_midi_channel_set *chset)
-{
- if (chset == NULL)
- return;
- kfree(chset->channels);
- kfree(chset);
-}
-
-static int __init alsa_seq_midi_emul_init(void)
-{
- return 0;
-}
-
-static void __exit alsa_seq_midi_emul_exit(void)
-{
-}
-
-module_init(alsa_seq_midi_emul_init)
-module_exit(alsa_seq_midi_emul_exit)
-
-EXPORT_SYMBOL(snd_midi_process_event);
-EXPORT_SYMBOL(snd_midi_channel_set_clear);
-EXPORT_SYMBOL(snd_midi_channel_alloc_set);
-EXPORT_SYMBOL(snd_midi_channel_free_set);
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_midi_event.c b/ANDROID_3.4.5/sound/core/seq/seq_midi_event.c
deleted file mode 100644
index 37db7ba4..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_midi_event.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
- * MIDI byte <-> sequencer event coder
- *
- * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>,
- * Jaroslav Kysela <perex@perex.cz>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/seq_kernel.h>
-#include <sound/seq_midi_event.h>
-#include <sound/asoundef.h>
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("MIDI byte <-> sequencer event coder");
-MODULE_LICENSE("GPL");
-
-/* event type, index into status_event[] */
-/* from 0 to 6 are normal commands (note off, on, etc.) for 0x9?-0xe? */
-#define ST_INVALID 7
-#define ST_SPECIAL 8
-#define ST_SYSEX ST_SPECIAL
-/* from 8 to 15 are events for 0xf0-0xf7 */
-
-
-/*
- * prototypes
- */
-static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
-static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
-static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
-static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
-static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
-static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
-static void note_decode(struct snd_seq_event *ev, unsigned char *buf);
-static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf);
-static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf);
-static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf);
-static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf);
-
-/*
- * event list
- */
-static struct status_event_list {
- int event;
- int qlen;
- void (*encode)(struct snd_midi_event *dev, struct snd_seq_event *ev);
- void (*decode)(struct snd_seq_event *ev, unsigned char *buf);
-} status_event[] = {
- /* 0x80 - 0xef */
- {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode},
- {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode},
- {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode},
- {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode},
- {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode},
- {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode},
- {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode},
- /* invalid */
- {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL},
- /* 0xf0 - 0xff */
- {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */
- {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */
- {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */
- {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */
- {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf4 */
- {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf5 */
- {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */
- {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf7 */
- {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */
- {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf9 */
- {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */
- {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */
- {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */
- {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xfd */
- {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */
- {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */
-};
-
-static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len,
- struct snd_seq_event *ev);
-static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, int count,
- struct snd_seq_event *ev);
-
-static struct extra_event_list {
- int event;
- int (*decode)(struct snd_midi_event *dev, unsigned char *buf, int len,
- struct snd_seq_event *ev);
-} extra_event[] = {
- {SNDRV_SEQ_EVENT_CONTROL14, extra_decode_ctrl14},
- {SNDRV_SEQ_EVENT_NONREGPARAM, extra_decode_xrpn},
- {SNDRV_SEQ_EVENT_REGPARAM, extra_decode_xrpn},
-};
-
-/*
- * new/delete record
- */
-
-int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev)
-{
- struct snd_midi_event *dev;
-
- *rdev = NULL;
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL)
- return -ENOMEM;
- if (bufsize > 0) {
- dev->buf = kmalloc(bufsize, GFP_KERNEL);
- if (dev->buf == NULL) {
- kfree(dev);
- return -ENOMEM;
- }
- }
- dev->bufsize = bufsize;
- dev->lastcmd = 0xff;
- dev->type = ST_INVALID;
- spin_lock_init(&dev->lock);
- *rdev = dev;
- return 0;
-}
-
-void snd_midi_event_free(struct snd_midi_event *dev)
-{
- if (dev != NULL) {
- kfree(dev->buf);
- kfree(dev);
- }
-}
-
-/*
- * initialize record
- */
-static inline void reset_encode(struct snd_midi_event *dev)
-{
- dev->read = 0;
- dev->qlen = 0;
- dev->type = ST_INVALID;
-}
-
-void snd_midi_event_reset_encode(struct snd_midi_event *dev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dev->lock, flags);
- reset_encode(dev);
- spin_unlock_irqrestore(&dev->lock, flags);
-}
-
-void snd_midi_event_reset_decode(struct snd_midi_event *dev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dev->lock, flags);
- dev->lastcmd = 0xff;
- spin_unlock_irqrestore(&dev->lock, flags);
-}
-
-#if 0
-void snd_midi_event_init(struct snd_midi_event *dev)
-{
- snd_midi_event_reset_encode(dev);
- snd_midi_event_reset_decode(dev);
-}
-#endif /* 0 */
-
-void snd_midi_event_no_status(struct snd_midi_event *dev, int on)
-{
- dev->nostat = on ? 1 : 0;
-}
-
-/*
- * resize buffer
- */
-#if 0
-int snd_midi_event_resize_buffer(struct snd_midi_event *dev, int bufsize)
-{
- unsigned char *new_buf, *old_buf;
- unsigned long flags;
-
- if (bufsize == dev->bufsize)
- return 0;
- new_buf = kmalloc(bufsize, GFP_KERNEL);
- if (new_buf == NULL)
- return -ENOMEM;
- spin_lock_irqsave(&dev->lock, flags);
- old_buf = dev->buf;
- dev->buf = new_buf;
- dev->bufsize = bufsize;
- reset_encode(dev);
- spin_unlock_irqrestore(&dev->lock, flags);
- kfree(old_buf);
- return 0;
-}
-#endif /* 0 */
-
-/*
- * read bytes and encode to sequencer event if finished
- * return the size of encoded bytes
- */
-long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count,
- struct snd_seq_event *ev)
-{
- long result = 0;
- int rc;
-
- ev->type = SNDRV_SEQ_EVENT_NONE;
-
- while (count-- > 0) {
- rc = snd_midi_event_encode_byte(dev, *buf++, ev);
- result++;
- if (rc < 0)
- return rc;
- else if (rc > 0)
- return result;
- }
-
- return result;
-}
-
-/*
- * read one byte and encode to sequencer event:
- * return 1 if MIDI bytes are encoded to an event
- * 0 data is not finished
- * negative for error
- */
-int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c,
- struct snd_seq_event *ev)
-{
- int rc = 0;
- unsigned long flags;
-
- c &= 0xff;
-
- if (c >= MIDI_CMD_COMMON_CLOCK) {
- /* real-time event */
- ev->type = status_event[ST_SPECIAL + c - 0xf0].event;
- ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
- ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
- return ev->type != SNDRV_SEQ_EVENT_NONE;
- }
-
- spin_lock_irqsave(&dev->lock, flags);
- if ((c & 0x80) &&
- (c != MIDI_CMD_COMMON_SYSEX_END || dev->type != ST_SYSEX)) {
- /* new command */
- dev->buf[0] = c;
- if ((c & 0xf0) == 0xf0) /* system messages */
- dev->type = (c & 0x0f) + ST_SPECIAL;
- else
- dev->type = (c >> 4) & 0x07;
- dev->read = 1;
- dev->qlen = status_event[dev->type].qlen;
- } else {
- if (dev->qlen > 0) {
- /* rest of command */
- dev->buf[dev->read++] = c;
- if (dev->type != ST_SYSEX)
- dev->qlen--;
- } else {
- /* running status */
- dev->buf[1] = c;
- dev->qlen = status_event[dev->type].qlen - 1;
- dev->read = 2;
- }
- }
- if (dev->qlen == 0) {
- ev->type = status_event[dev->type].event;
- ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
- ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
- if (status_event[dev->type].encode) /* set data values */
- status_event[dev->type].encode(dev, ev);
- if (dev->type >= ST_SPECIAL)
- dev->type = ST_INVALID;
- rc = 1;
- } else if (dev->type == ST_SYSEX) {
- if (c == MIDI_CMD_COMMON_SYSEX_END ||
- dev->read >= dev->bufsize) {
- ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
- ev->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
- ev->type = SNDRV_SEQ_EVENT_SYSEX;
- ev->data.ext.len = dev->read;
- ev->data.ext.ptr = dev->buf;
- if (c != MIDI_CMD_COMMON_SYSEX_END)
- dev->read = 0; /* continue to parse */
- else
- reset_encode(dev); /* all parsed */
- rc = 1;
- }
- }
-
- spin_unlock_irqrestore(&dev->lock, flags);
- return rc;
-}
-
-/* encode note event */
-static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
-{
- ev->data.note.channel = dev->buf[0] & 0x0f;
- ev->data.note.note = dev->buf[1];
- ev->data.note.velocity = dev->buf[2];
-}
-
-/* encode one parameter controls */
-static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
-{
- ev->data.control.channel = dev->buf[0] & 0x0f;
- ev->data.control.value = dev->buf[1];
-}
-
-/* encode pitch wheel change */
-static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
-{
- ev->data.control.channel = dev->buf[0] & 0x0f;
- ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1] - 8192;
-}
-
-/* encode midi control change */
-static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
-{
- ev->data.control.channel = dev->buf[0] & 0x0f;
- ev->data.control.param = dev->buf[1];
- ev->data.control.value = dev->buf[2];
-}
-
-/* encode one parameter value*/
-static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
-{
- ev->data.control.value = dev->buf[1];
-}
-
-/* encode song position */
-static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
-{
- ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1];
-}
-
-/*
- * decode from a sequencer event to midi bytes
- * return the size of decoded midi events
- */
-long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long count,
- struct snd_seq_event *ev)
-{
- unsigned int cmd, type;
-
- if (ev->type == SNDRV_SEQ_EVENT_NONE)
- return -ENOENT;
-
- for (type = 0; type < ARRAY_SIZE(status_event); type++) {
- if (ev->type == status_event[type].event)
- goto __found;
- }
- for (type = 0; type < ARRAY_SIZE(extra_event); type++) {
- if (ev->type == extra_event[type].event)
- return extra_event[type].decode(dev, buf, count, ev);
- }
- return -ENOENT;
-
- __found:
- if (type >= ST_SPECIAL)
- cmd = 0xf0 + (type - ST_SPECIAL);
- else
- /* data.note.channel and data.control.channel is identical */
- cmd = 0x80 | (type << 4) | (ev->data.note.channel & 0x0f);
-
-
- if (cmd == MIDI_CMD_COMMON_SYSEX) {
- snd_midi_event_reset_decode(dev);
- return snd_seq_expand_var_event(ev, count, buf, 1, 0);
- } else {
- int qlen;
- unsigned char xbuf[4];
- unsigned long flags;
-
- spin_lock_irqsave(&dev->lock, flags);
- if ((cmd & 0xf0) == 0xf0 || dev->lastcmd != cmd || dev->nostat) {
- dev->lastcmd = cmd;
- spin_unlock_irqrestore(&dev->lock, flags);
- xbuf[0] = cmd;
- if (status_event[type].decode)
- status_event[type].decode(ev, xbuf + 1);
- qlen = status_event[type].qlen + 1;
- } else {
- spin_unlock_irqrestore(&dev->lock, flags);
- if (status_event[type].decode)
- status_event[type].decode(ev, xbuf + 0);
- qlen = status_event[type].qlen;
- }
- if (count < qlen)
- return -ENOMEM;
- memcpy(buf, xbuf, qlen);
- return qlen;
- }
-}
-
-
-/* decode note event */
-static void note_decode(struct snd_seq_event *ev, unsigned char *buf)
-{
- buf[0] = ev->data.note.note & 0x7f;
- buf[1] = ev->data.note.velocity & 0x7f;
-}
-
-/* decode one parameter controls */
-static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf)
-{
- buf[0] = ev->data.control.value & 0x7f;
-}
-
-/* decode pitch wheel change */
-static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf)
-{
- int value = ev->data.control.value + 8192;
- buf[0] = value & 0x7f;
- buf[1] = (value >> 7) & 0x7f;
-}
-
-/* decode midi control change */
-static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf)
-{
- buf[0] = ev->data.control.param & 0x7f;
- buf[1] = ev->data.control.value & 0x7f;
-}
-
-/* decode song position */
-static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf)
-{
- buf[0] = ev->data.control.value & 0x7f;
- buf[1] = (ev->data.control.value >> 7) & 0x7f;
-}
-
-/* decode 14bit control */
-static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf,
- int count, struct snd_seq_event *ev)
-{
- unsigned char cmd;
- int idx = 0;
-
- cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
- if (ev->data.control.param < 0x20) {
- if (count < 4)
- return -ENOMEM;
- if (dev->nostat && count < 6)
- return -ENOMEM;
- if (cmd != dev->lastcmd || dev->nostat) {
- if (count < 5)
- return -ENOMEM;
- buf[idx++] = dev->lastcmd = cmd;
- }
- buf[idx++] = ev->data.control.param;
- buf[idx++] = (ev->data.control.value >> 7) & 0x7f;
- if (dev->nostat)
- buf[idx++] = cmd;
- buf[idx++] = ev->data.control.param + 0x20;
- buf[idx++] = ev->data.control.value & 0x7f;
- } else {
- if (count < 2)
- return -ENOMEM;
- if (cmd != dev->lastcmd || dev->nostat) {
- if (count < 3)
- return -ENOMEM;
- buf[idx++] = dev->lastcmd = cmd;
- }
- buf[idx++] = ev->data.control.param & 0x7f;
- buf[idx++] = ev->data.control.value & 0x7f;
- }
- return idx;
-}
-
-/* decode reg/nonreg param */
-static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf,
- int count, struct snd_seq_event *ev)
-{
- unsigned char cmd;
- char *cbytes;
- static char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB,
- MIDI_CTL_NONREG_PARM_NUM_LSB,
- MIDI_CTL_MSB_DATA_ENTRY,
- MIDI_CTL_LSB_DATA_ENTRY };
- static char cbytes_rpn[4] = { MIDI_CTL_REGIST_PARM_NUM_MSB,
- MIDI_CTL_REGIST_PARM_NUM_LSB,
- MIDI_CTL_MSB_DATA_ENTRY,
- MIDI_CTL_LSB_DATA_ENTRY };
- unsigned char bytes[4];
- int idx = 0, i;
-
- if (count < 8)
- return -ENOMEM;
- if (dev->nostat && count < 12)
- return -ENOMEM;
- cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
- bytes[0] = (ev->data.control.param & 0x3f80) >> 7;
- bytes[1] = ev->data.control.param & 0x007f;
- bytes[2] = (ev->data.control.value & 0x3f80) >> 7;
- bytes[3] = ev->data.control.value & 0x007f;
- if (cmd != dev->lastcmd && !dev->nostat) {
- if (count < 9)
- return -ENOMEM;
- buf[idx++] = dev->lastcmd = cmd;
- }
- cbytes = ev->type == SNDRV_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn;
- for (i = 0; i < 4; i++) {
- if (dev->nostat)
- buf[idx++] = dev->lastcmd = cmd;
- buf[idx++] = cbytes[i];
- buf[idx++] = bytes[i];
- }
- return idx;
-}
-
-/*
- * exports
- */
-
-EXPORT_SYMBOL(snd_midi_event_new);
-EXPORT_SYMBOL(snd_midi_event_free);
-EXPORT_SYMBOL(snd_midi_event_reset_encode);
-EXPORT_SYMBOL(snd_midi_event_reset_decode);
-EXPORT_SYMBOL(snd_midi_event_no_status);
-EXPORT_SYMBOL(snd_midi_event_encode);
-EXPORT_SYMBOL(snd_midi_event_encode_byte);
-EXPORT_SYMBOL(snd_midi_event_decode);
-
-static int __init alsa_seq_midi_event_init(void)
-{
- return 0;
-}
-
-static void __exit alsa_seq_midi_event_exit(void)
-{
-}
-
-module_init(alsa_seq_midi_event_init)
-module_exit(alsa_seq_midi_event_exit)
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_ports.c b/ANDROID_3.4.5/sound/core/seq/seq_ports.c
deleted file mode 100644
index 9516e5ce..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_ports.c
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
- * ALSA sequencer Ports
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <sound/core.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include "seq_system.h"
-#include "seq_ports.h"
-#include "seq_clientmgr.h"
-
-/*
-
- registration of client ports
-
- */
-
-
-/*
-
-NOTE: the current implementation of the port structure as a linked list is
-not optimal for clients that have many ports. For sending messages to all
-subscribers of a port we first need to find the address of the port
-structure, which means we have to traverse the list. A direct access table
-(array) would be better, but big preallocated arrays waste memory.
-
-Possible actions:
-
-1) leave it this way, a client does normaly does not have more than a few
-ports
-
-2) replace the linked list of ports by a array of pointers which is
-dynamicly kmalloced. When a port is added or deleted we can simply allocate
-a new array, copy the corresponding pointers, and delete the old one. We
-then only need a pointer to this array, and an integer that tells us how
-much elements are in array.
-
-*/
-
-/* return pointer to port structure - port is locked if found */
-struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client,
- int num)
-{
- struct snd_seq_client_port *port;
-
- if (client == NULL)
- return NULL;
- read_lock(&client->ports_lock);
- list_for_each_entry(port, &client->ports_list_head, list) {
- if (port->addr.port == num) {
- if (port->closing)
- break; /* deleting now */
- snd_use_lock_use(&port->use_lock);
- read_unlock(&client->ports_lock);
- return port;
- }
- }
- read_unlock(&client->ports_lock);
- return NULL; /* not found */
-}
-
-
-/* search for the next port - port is locked if found */
-struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client,
- struct snd_seq_port_info *pinfo)
-{
- int num;
- struct snd_seq_client_port *port, *found;
-
- num = pinfo->addr.port;
- found = NULL;
- read_lock(&client->ports_lock);
- list_for_each_entry(port, &client->ports_list_head, list) {
- if (port->addr.port < num)
- continue;
- if (port->addr.port == num) {
- found = port;
- break;
- }
- if (found == NULL || port->addr.port < found->addr.port)
- found = port;
- }
- if (found) {
- if (found->closing)
- found = NULL;
- else
- snd_use_lock_use(&found->use_lock);
- }
- read_unlock(&client->ports_lock);
- return found;
-}
-
-
-/* initialize snd_seq_port_subs_info */
-static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
-{
- INIT_LIST_HEAD(&grp->list_head);
- grp->count = 0;
- grp->exclusive = 0;
- rwlock_init(&grp->list_lock);
- init_rwsem(&grp->list_mutex);
- grp->open = NULL;
- grp->close = NULL;
-}
-
-
-/* create a port, port number is returned (-1 on failure) */
-struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
- int port)
-{
- unsigned long flags;
- struct snd_seq_client_port *new_port, *p;
- int num = -1;
-
- /* sanity check */
- if (snd_BUG_ON(!client))
- return NULL;
-
- if (client->num_ports >= SNDRV_SEQ_MAX_PORTS - 1) {
- snd_printk(KERN_WARNING "too many ports for client %d\n", client->number);
- return NULL;
- }
-
- /* create a new port */
- new_port = kzalloc(sizeof(*new_port), GFP_KERNEL);
- if (! new_port) {
- snd_printd("malloc failed for registering client port\n");
- return NULL; /* failure, out of memory */
- }
- /* init port data */
- new_port->addr.client = client->number;
- new_port->addr.port = -1;
- new_port->owner = THIS_MODULE;
- sprintf(new_port->name, "port-%d", num);
- snd_use_lock_init(&new_port->use_lock);
- port_subs_info_init(&new_port->c_src);
- port_subs_info_init(&new_port->c_dest);
-
- num = port >= 0 ? port : 0;
- mutex_lock(&client->ports_mutex);
- write_lock_irqsave(&client->ports_lock, flags);
- list_for_each_entry(p, &client->ports_list_head, list) {
- if (p->addr.port > num)
- break;
- if (port < 0) /* auto-probe mode */
- num = p->addr.port + 1;
- }
- /* insert the new port */
- list_add_tail(&new_port->list, &p->list);
- client->num_ports++;
- new_port->addr.port = num; /* store the port number in the port */
- write_unlock_irqrestore(&client->ports_lock, flags);
- mutex_unlock(&client->ports_mutex);
- sprintf(new_port->name, "port-%d", num);
-
- return new_port;
-}
-
-/* */
-enum group_type {
- SRC_LIST, DEST_LIST
-};
-
-static int subscribe_port(struct snd_seq_client *client,
- struct snd_seq_client_port *port,
- struct snd_seq_port_subs_info *grp,
- struct snd_seq_port_subscribe *info, int send_ack);
-static int unsubscribe_port(struct snd_seq_client *client,
- struct snd_seq_client_port *port,
- struct snd_seq_port_subs_info *grp,
- struct snd_seq_port_subscribe *info, int send_ack);
-
-
-static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
- struct snd_seq_client **cp)
-{
- struct snd_seq_client_port *p;
- *cp = snd_seq_client_use_ptr(addr->client);
- if (*cp) {
- p = snd_seq_port_use_ptr(*cp, addr->port);
- if (! p) {
- snd_seq_client_unlock(*cp);
- *cp = NULL;
- }
- return p;
- }
- return NULL;
-}
-
-/*
- * remove all subscribers on the list
- * this is called from port_delete, for each src and dest list.
- */
-static void clear_subscriber_list(struct snd_seq_client *client,
- struct snd_seq_client_port *port,
- struct snd_seq_port_subs_info *grp,
- int grptype)
-{
- struct list_head *p, *n;
-
- list_for_each_safe(p, n, &grp->list_head) {
- struct snd_seq_subscribers *subs;
- struct snd_seq_client *c;
- struct snd_seq_client_port *aport;
-
- if (grptype == SRC_LIST) {
- subs = list_entry(p, struct snd_seq_subscribers, src_list);
- aport = get_client_port(&subs->info.dest, &c);
- } else {
- subs = list_entry(p, struct snd_seq_subscribers, dest_list);
- aport = get_client_port(&subs->info.sender, &c);
- }
- list_del(p);
- unsubscribe_port(client, port, grp, &subs->info, 0);
- if (!aport) {
- /* looks like the connected port is being deleted.
- * we decrease the counter, and when both ports are deleted
- * remove the subscriber info
- */
- if (atomic_dec_and_test(&subs->ref_count))
- kfree(subs);
- } else {
- /* ok we got the connected port */
- struct snd_seq_port_subs_info *agrp;
- agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src;
- down_write(&agrp->list_mutex);
- if (grptype == SRC_LIST)
- list_del(&subs->dest_list);
- else
- list_del(&subs->src_list);
- up_write(&agrp->list_mutex);
- unsubscribe_port(c, aport, agrp, &subs->info, 1);
- kfree(subs);
- snd_seq_port_unlock(aport);
- snd_seq_client_unlock(c);
- }
- }
-}
-
-/* delete port data */
-static int port_delete(struct snd_seq_client *client,
- struct snd_seq_client_port *port)
-{
- /* set closing flag and wait for all port access are gone */
- port->closing = 1;
- snd_use_lock_sync(&port->use_lock);
-
- /* clear subscribers info */
- clear_subscriber_list(client, port, &port->c_src, SRC_LIST);
- clear_subscriber_list(client, port, &port->c_dest, DEST_LIST);
-
- if (port->private_free)
- port->private_free(port->private_data);
-
- snd_BUG_ON(port->c_src.count != 0);
- snd_BUG_ON(port->c_dest.count != 0);
-
- kfree(port);
- return 0;
-}
-
-
-/* delete a port with the given port id */
-int snd_seq_delete_port(struct snd_seq_client *client, int port)
-{
- unsigned long flags;
- struct snd_seq_client_port *found = NULL, *p;
-
- mutex_lock(&client->ports_mutex);
- write_lock_irqsave(&client->ports_lock, flags);
- list_for_each_entry(p, &client->ports_list_head, list) {
- if (p->addr.port == port) {
- /* ok found. delete from the list at first */
- list_del(&p->list);
- client->num_ports--;
- found = p;
- break;
- }
- }
- write_unlock_irqrestore(&client->ports_lock, flags);
- mutex_unlock(&client->ports_mutex);
- if (found)
- return port_delete(client, found);
- else
- return -ENOENT;
-}
-
-/* delete the all ports belonging to the given client */
-int snd_seq_delete_all_ports(struct snd_seq_client *client)
-{
- unsigned long flags;
- struct list_head deleted_list;
- struct snd_seq_client_port *port, *tmp;
-
- /* move the port list to deleted_list, and
- * clear the port list in the client data.
- */
- mutex_lock(&client->ports_mutex);
- write_lock_irqsave(&client->ports_lock, flags);
- if (! list_empty(&client->ports_list_head)) {
- list_add(&deleted_list, &client->ports_list_head);
- list_del_init(&client->ports_list_head);
- } else {
- INIT_LIST_HEAD(&deleted_list);
- }
- client->num_ports = 0;
- write_unlock_irqrestore(&client->ports_lock, flags);
-
- /* remove each port in deleted_list */
- list_for_each_entry_safe(port, tmp, &deleted_list, list) {
- list_del(&port->list);
- snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port);
- port_delete(client, port);
- }
- mutex_unlock(&client->ports_mutex);
- return 0;
-}
-
-/* set port info fields */
-int snd_seq_set_port_info(struct snd_seq_client_port * port,
- struct snd_seq_port_info * info)
-{
- if (snd_BUG_ON(!port || !info))
- return -EINVAL;
-
- /* set port name */
- if (info->name[0])
- strlcpy(port->name, info->name, sizeof(port->name));
-
- /* set capabilities */
- port->capability = info->capability;
-
- /* get port type */
- port->type = info->type;
-
- /* information about supported channels/voices */
- port->midi_channels = info->midi_channels;
- port->midi_voices = info->midi_voices;
- port->synth_voices = info->synth_voices;
-
- /* timestamping */
- port->timestamping = (info->flags & SNDRV_SEQ_PORT_FLG_TIMESTAMP) ? 1 : 0;
- port->time_real = (info->flags & SNDRV_SEQ_PORT_FLG_TIME_REAL) ? 1 : 0;
- port->time_queue = info->time_queue;
-
- return 0;
-}
-
-/* get port info fields */
-int snd_seq_get_port_info(struct snd_seq_client_port * port,
- struct snd_seq_port_info * info)
-{
- if (snd_BUG_ON(!port || !info))
- return -EINVAL;
-
- /* get port name */
- strlcpy(info->name, port->name, sizeof(info->name));
-
- /* get capabilities */
- info->capability = port->capability;
-
- /* get port type */
- info->type = port->type;
-
- /* information about supported channels/voices */
- info->midi_channels = port->midi_channels;
- info->midi_voices = port->midi_voices;
- info->synth_voices = port->synth_voices;
-
- /* get subscriber counts */
- info->read_use = port->c_src.count;
- info->write_use = port->c_dest.count;
-
- /* timestamping */
- info->flags = 0;
- if (port->timestamping) {
- info->flags |= SNDRV_SEQ_PORT_FLG_TIMESTAMP;
- if (port->time_real)
- info->flags |= SNDRV_SEQ_PORT_FLG_TIME_REAL;
- info->time_queue = port->time_queue;
- }
-
- return 0;
-}
-
-
-
-/*
- * call callback functions (if any):
- * the callbacks are invoked only when the first (for connection) or
- * the last subscription (for disconnection) is done. Second or later
- * subscription results in increment of counter, but no callback is
- * invoked.
- * This feature is useful if these callbacks are associated with
- * initialization or termination of devices (see seq_midi.c).
- *
- * If callback_all option is set, the callback function is invoked
- * at each connection/disconnection.
- */
-
-static int subscribe_port(struct snd_seq_client *client,
- struct snd_seq_client_port *port,
- struct snd_seq_port_subs_info *grp,
- struct snd_seq_port_subscribe *info,
- int send_ack)
-{
- int err = 0;
-
- if (!try_module_get(port->owner))
- return -EFAULT;
- grp->count++;
- if (grp->open && (port->callback_all || grp->count == 1)) {
- err = grp->open(port->private_data, info);
- if (err < 0) {
- module_put(port->owner);
- grp->count--;
- }
- }
- if (err >= 0 && send_ack && client->type == USER_CLIENT)
- snd_seq_client_notify_subscription(port->addr.client, port->addr.port,
- info, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);
-
- return err;
-}
-
-static int unsubscribe_port(struct snd_seq_client *client,
- struct snd_seq_client_port *port,
- struct snd_seq_port_subs_info *grp,
- struct snd_seq_port_subscribe *info,
- int send_ack)
-{
- int err = 0;
-
- if (! grp->count)
- return -EINVAL;
- grp->count--;
- if (grp->close && (port->callback_all || grp->count == 0))
- err = grp->close(port->private_data, info);
- if (send_ack && client->type == USER_CLIENT)
- snd_seq_client_notify_subscription(port->addr.client, port->addr.port,
- info, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);
- module_put(port->owner);
- return err;
-}
-
-
-
-/* check if both addresses are identical */
-static inline int addr_match(struct snd_seq_addr *r, struct snd_seq_addr *s)
-{
- return (r->client == s->client) && (r->port == s->port);
-}
-
-/* check the two subscribe info match */
-/* if flags is zero, checks only sender and destination addresses */
-static int match_subs_info(struct snd_seq_port_subscribe *r,
- struct snd_seq_port_subscribe *s)
-{
- if (addr_match(&r->sender, &s->sender) &&
- addr_match(&r->dest, &s->dest)) {
- if (r->flags && r->flags == s->flags)
- return r->queue == s->queue;
- else if (! r->flags)
- return 1;
- }
- return 0;
-}
-
-
-/* connect two ports */
-int snd_seq_port_connect(struct snd_seq_client *connector,
- struct snd_seq_client *src_client,
- struct snd_seq_client_port *src_port,
- struct snd_seq_client *dest_client,
- struct snd_seq_client_port *dest_port,
- struct snd_seq_port_subscribe *info)
-{
- struct snd_seq_port_subs_info *src = &src_port->c_src;
- struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
- struct snd_seq_subscribers *subs, *s;
- int err, src_called = 0;
- unsigned long flags;
- int exclusive;
-
- subs = kzalloc(sizeof(*subs), GFP_KERNEL);
- if (! subs)
- return -ENOMEM;
-
- subs->info = *info;
- atomic_set(&subs->ref_count, 2);
-
- down_write(&src->list_mutex);
- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
-
- exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0;
- err = -EBUSY;
- if (exclusive) {
- if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head))
- goto __error;
- } else {
- if (src->exclusive || dest->exclusive)
- goto __error;
- /* check whether already exists */
- list_for_each_entry(s, &src->list_head, src_list) {
- if (match_subs_info(info, &s->info))
- goto __error;
- }
- list_for_each_entry(s, &dest->list_head, dest_list) {
- if (match_subs_info(info, &s->info))
- goto __error;
- }
- }
-
- if ((err = subscribe_port(src_client, src_port, src, info,
- connector->number != src_client->number)) < 0)
- goto __error;
- src_called = 1;
-
- if ((err = subscribe_port(dest_client, dest_port, dest, info,
- connector->number != dest_client->number)) < 0)
- goto __error;
-
- /* add to list */
- write_lock_irqsave(&src->list_lock, flags);
- // write_lock(&dest->list_lock); // no other lock yet
- list_add_tail(&subs->src_list, &src->list_head);
- list_add_tail(&subs->dest_list, &dest->list_head);
- // write_unlock(&dest->list_lock); // no other lock yet
- write_unlock_irqrestore(&src->list_lock, flags);
-
- src->exclusive = dest->exclusive = exclusive;
-
- up_write(&dest->list_mutex);
- up_write(&src->list_mutex);
- return 0;
-
- __error:
- if (src_called)
- unsubscribe_port(src_client, src_port, src, info,
- connector->number != src_client->number);
- kfree(subs);
- up_write(&dest->list_mutex);
- up_write(&src->list_mutex);
- return err;
-}
-
-
-/* remove the connection */
-int snd_seq_port_disconnect(struct snd_seq_client *connector,
- struct snd_seq_client *src_client,
- struct snd_seq_client_port *src_port,
- struct snd_seq_client *dest_client,
- struct snd_seq_client_port *dest_port,
- struct snd_seq_port_subscribe *info)
-{
- struct snd_seq_port_subs_info *src = &src_port->c_src;
- struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
- struct snd_seq_subscribers *subs;
- int err = -ENOENT;
- unsigned long flags;
-
- down_write(&src->list_mutex);
- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
-
- /* look for the connection */
- list_for_each_entry(subs, &src->list_head, src_list) {
- if (match_subs_info(info, &subs->info)) {
- write_lock_irqsave(&src->list_lock, flags);
- // write_lock(&dest->list_lock); // no lock yet
- list_del(&subs->src_list);
- list_del(&subs->dest_list);
- // write_unlock(&dest->list_lock);
- write_unlock_irqrestore(&src->list_lock, flags);
- src->exclusive = dest->exclusive = 0;
- unsubscribe_port(src_client, src_port, src, info,
- connector->number != src_client->number);
- unsubscribe_port(dest_client, dest_port, dest, info,
- connector->number != dest_client->number);
- kfree(subs);
- err = 0;
- break;
- }
- }
-
- up_write(&dest->list_mutex);
- up_write(&src->list_mutex);
- return err;
-}
-
-
-/* get matched subscriber */
-struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
- struct snd_seq_addr *dest_addr)
-{
- struct snd_seq_subscribers *s, *found = NULL;
-
- down_read(&src_grp->list_mutex);
- list_for_each_entry(s, &src_grp->list_head, src_list) {
- if (addr_match(dest_addr, &s->info.dest)) {
- found = s;
- break;
- }
- }
- up_read(&src_grp->list_mutex);
- return found;
-}
-
-/*
- * Attach a device driver that wants to receive events from the
- * sequencer. Returns the new port number on success.
- * A driver that wants to receive the events converted to midi, will
- * use snd_seq_midisynth_register_port().
- */
-/* exported */
-int snd_seq_event_port_attach(int client,
- struct snd_seq_port_callback *pcbp,
- int cap, int type, int midi_channels,
- int midi_voices, char *portname)
-{
- struct snd_seq_port_info portinfo;
- int ret;
-
- /* Set up the port */
- memset(&portinfo, 0, sizeof(portinfo));
- portinfo.addr.client = client;
- strlcpy(portinfo.name, portname ? portname : "Unamed port",
- sizeof(portinfo.name));
-
- portinfo.capability = cap;
- portinfo.type = type;
- portinfo.kernel = pcbp;
- portinfo.midi_channels = midi_channels;
- portinfo.midi_voices = midi_voices;
-
- /* Create it */
- ret = snd_seq_kernel_client_ctl(client,
- SNDRV_SEQ_IOCTL_CREATE_PORT,
- &portinfo);
-
- if (ret >= 0)
- ret = portinfo.addr.port;
-
- return ret;
-}
-
-EXPORT_SYMBOL(snd_seq_event_port_attach);
-
-/*
- * Detach the driver from a port.
- */
-/* exported */
-int snd_seq_event_port_detach(int client, int port)
-{
- struct snd_seq_port_info portinfo;
- int err;
-
- memset(&portinfo, 0, sizeof(portinfo));
- portinfo.addr.client = client;
- portinfo.addr.port = port;
- err = snd_seq_kernel_client_ctl(client,
- SNDRV_SEQ_IOCTL_DELETE_PORT,
- &portinfo);
-
- return err;
-}
-
-EXPORT_SYMBOL(snd_seq_event_port_detach);
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_ports.h b/ANDROID_3.4.5/sound/core/seq/seq_ports.h
deleted file mode 100644
index 9d711711..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_ports.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * ALSA sequencer Ports
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __SND_SEQ_PORTS_H
-#define __SND_SEQ_PORTS_H
-
-#include <sound/seq_kernel.h>
-#include "seq_lock.h"
-
-/* list of 'exported' ports */
-
-/* Client ports that are not exported are still accessible, but are
- anonymous ports.
-
- If a port supports SUBSCRIPTION, that port can send events to all
- subscribersto a special address, with address
- (queue==SNDRV_SEQ_ADDRESS_SUBSCRIBERS). The message is then send to all
- recipients that are registered in the subscription list. A typical
- application for these SUBSCRIPTION events is handling of incoming MIDI
- data. The port doesn't 'know' what other clients are interested in this
- message. If for instance a MIDI recording application would like to receive
- the events from that port, it will first have to subscribe with that port.
-
-*/
-
-struct snd_seq_subscribers {
- struct snd_seq_port_subscribe info; /* additional info */
- struct list_head src_list; /* link of sources */
- struct list_head dest_list; /* link of destinations */
- atomic_t ref_count;
-};
-
-struct snd_seq_port_subs_info {
- struct list_head list_head; /* list of subscribed ports */
- unsigned int count; /* count of subscribers */
- unsigned int exclusive: 1; /* exclusive mode */
- struct rw_semaphore list_mutex;
- rwlock_t list_lock;
- int (*open)(void *private_data, struct snd_seq_port_subscribe *info);
- int (*close)(void *private_data, struct snd_seq_port_subscribe *info);
-};
-
-struct snd_seq_client_port {
-
- struct snd_seq_addr addr; /* client/port number */
- struct module *owner; /* owner of this port */
- char name[64]; /* port name */
- struct list_head list; /* port list */
- snd_use_lock_t use_lock;
-
- /* subscribers */
- struct snd_seq_port_subs_info c_src; /* read (sender) list */
- struct snd_seq_port_subs_info c_dest; /* write (dest) list */
-
- int (*event_input)(struct snd_seq_event *ev, int direct, void *private_data,
- int atomic, int hop);
- void (*private_free)(void *private_data);
- void *private_data;
- unsigned int callback_all : 1;
- unsigned int closing : 1;
- unsigned int timestamping: 1;
- unsigned int time_real: 1;
- int time_queue;
-
- /* capability, inport, output, sync */
- unsigned int capability; /* port capability bits */
- unsigned int type; /* port type bits */
-
- /* supported channels */
- int midi_channels;
- int midi_voices;
- int synth_voices;
-
-};
-
-struct snd_seq_client;
-
-/* return pointer to port structure and lock port */
-struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client, int num);
-
-/* search for next port - port is locked if found */
-struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client,
- struct snd_seq_port_info *pinfo);
-
-/* unlock the port */
-#define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock)
-
-/* create a port, port number is returned (-1 on failure) */
-struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, int port_index);
-
-/* delete a port */
-int snd_seq_delete_port(struct snd_seq_client *client, int port);
-
-/* delete all ports */
-int snd_seq_delete_all_ports(struct snd_seq_client *client);
-
-/* set port info fields */
-int snd_seq_set_port_info(struct snd_seq_client_port *port,
- struct snd_seq_port_info *info);
-
-/* get port info fields */
-int snd_seq_get_port_info(struct snd_seq_client_port *port,
- struct snd_seq_port_info *info);
-
-/* add subscriber to subscription list */
-int snd_seq_port_connect(struct snd_seq_client *caller,
- struct snd_seq_client *s, struct snd_seq_client_port *sp,
- struct snd_seq_client *d, struct snd_seq_client_port *dp,
- struct snd_seq_port_subscribe *info);
-
-/* remove subscriber from subscription list */
-int snd_seq_port_disconnect(struct snd_seq_client *caller,
- struct snd_seq_client *s, struct snd_seq_client_port *sp,
- struct snd_seq_client *d, struct snd_seq_client_port *dp,
- struct snd_seq_port_subscribe *info);
-
-/* subscribe port */
-int snd_seq_port_subscribe(struct snd_seq_client_port *port,
- struct snd_seq_port_subscribe *info);
-
-/* get matched subscriber */
-struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
- struct snd_seq_addr *dest_addr);
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_prioq.c b/ANDROID_3.4.5/sound/core/seq/seq_prioq.c
deleted file mode 100644
index 29896ab2..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_prioq.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * ALSA sequencer Priority Queue
- * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/time.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include "seq_timer.h"
-#include "seq_prioq.h"
-
-
-/* Implementation is a simple linked list for now...
-
- This priority queue orders the events on timestamp. For events with an
- equeal timestamp the queue behaves as a FIFO.
-
- *
- * +-------+
- * Head --> | first |
- * +-------+
- * |next
- * +-----v-+
- * | |
- * +-------+
- * |
- * +-----v-+
- * | |
- * +-------+
- * |
- * +-----v-+
- * Tail --> | last |
- * +-------+
- *
-
- */
-
-
-
-/* create new prioq (constructor) */
-struct snd_seq_prioq *snd_seq_prioq_new(void)
-{
- struct snd_seq_prioq *f;
-
- f = kzalloc(sizeof(*f), GFP_KERNEL);
- if (f == NULL) {
- snd_printd("oops: malloc failed for snd_seq_prioq_new()\n");
- return NULL;
- }
-
- spin_lock_init(&f->lock);
- f->head = NULL;
- f->tail = NULL;
- f->cells = 0;
-
- return f;
-}
-
-/* delete prioq (destructor) */
-void snd_seq_prioq_delete(struct snd_seq_prioq **fifo)
-{
- struct snd_seq_prioq *f = *fifo;
- *fifo = NULL;
-
- if (f == NULL) {
- snd_printd("oops: snd_seq_prioq_delete() called with NULL prioq\n");
- return;
- }
-
- /* release resources...*/
- /*....................*/
-
- if (f->cells > 0) {
- /* drain prioQ */
- while (f->cells > 0)
- snd_seq_cell_free(snd_seq_prioq_cell_out(f));
- }
-
- kfree(f);
-}
-
-
-
-
-/* compare timestamp between events */
-/* return 1 if a >= b; 0 */
-static inline int compare_timestamp(struct snd_seq_event *a,
- struct snd_seq_event *b)
-{
- if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) {
- /* compare ticks */
- return (snd_seq_compare_tick_time(&a->time.tick, &b->time.tick));
- } else {
- /* compare real time */
- return (snd_seq_compare_real_time(&a->time.time, &b->time.time));
- }
-}
-
-/* compare timestamp between events */
-/* return negative if a < b;
- * zero if a = b;
- * positive if a > b;
- */
-static inline int compare_timestamp_rel(struct snd_seq_event *a,
- struct snd_seq_event *b)
-{
- if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) {
- /* compare ticks */
- if (a->time.tick > b->time.tick)
- return 1;
- else if (a->time.tick == b->time.tick)
- return 0;
- else
- return -1;
- } else {
- /* compare real time */
- if (a->time.time.tv_sec > b->time.time.tv_sec)
- return 1;
- else if (a->time.time.tv_sec == b->time.time.tv_sec) {
- if (a->time.time.tv_nsec > b->time.time.tv_nsec)
- return 1;
- else if (a->time.time.tv_nsec == b->time.time.tv_nsec)
- return 0;
- else
- return -1;
- } else
- return -1;
- }
-}
-
-/* enqueue cell to prioq */
-int snd_seq_prioq_cell_in(struct snd_seq_prioq * f,
- struct snd_seq_event_cell * cell)
-{
- struct snd_seq_event_cell *cur, *prev;
- unsigned long flags;
- int count;
- int prior;
-
- if (snd_BUG_ON(!f || !cell))
- return -EINVAL;
-
- /* check flags */
- prior = (cell->event.flags & SNDRV_SEQ_PRIORITY_MASK);
-
- spin_lock_irqsave(&f->lock, flags);
-
- /* check if this element needs to inserted at the end (ie. ordered
- data is inserted) This will be very likeley if a sequencer
- application or midi file player is feeding us (sequential) data */
- if (f->tail && !prior) {
- if (compare_timestamp(&cell->event, &f->tail->event)) {
- /* add new cell to tail of the fifo */
- f->tail->next = cell;
- f->tail = cell;
- cell->next = NULL;
- f->cells++;
- spin_unlock_irqrestore(&f->lock, flags);
- return 0;
- }
- }
- /* traverse list of elements to find the place where the new cell is
- to be inserted... Note that this is a order n process ! */
-
- prev = NULL; /* previous cell */
- cur = f->head; /* cursor */
-
- count = 10000; /* FIXME: enough big, isn't it? */
- while (cur != NULL) {
- /* compare timestamps */
- int rel = compare_timestamp_rel(&cell->event, &cur->event);
- if (rel < 0)
- /* new cell has earlier schedule time, */
- break;
- else if (rel == 0 && prior)
- /* equal schedule time and prior to others */
- break;
- /* new cell has equal or larger schedule time, */
- /* move cursor to next cell */
- prev = cur;
- cur = cur->next;
- if (! --count) {
- spin_unlock_irqrestore(&f->lock, flags);
- snd_printk(KERN_ERR "cannot find a pointer.. infinite loop?\n");
- return -EINVAL;
- }
- }
-
- /* insert it before cursor */
- if (prev != NULL)
- prev->next = cell;
- cell->next = cur;
-
- if (f->head == cur) /* this is the first cell, set head to it */
- f->head = cell;
- if (cur == NULL) /* reached end of the list */
- f->tail = cell;
- f->cells++;
- spin_unlock_irqrestore(&f->lock, flags);
- return 0;
-}
-
-/* dequeue cell from prioq */
-struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f)
-{
- struct snd_seq_event_cell *cell;
- unsigned long flags;
-
- if (f == NULL) {
- snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n");
- return NULL;
- }
- spin_lock_irqsave(&f->lock, flags);
-
- cell = f->head;
- if (cell) {
- f->head = cell->next;
-
- /* reset tail if this was the last element */
- if (f->tail == cell)
- f->tail = NULL;
-
- cell->next = NULL;
- f->cells--;
- }
-
- spin_unlock_irqrestore(&f->lock, flags);
- return cell;
-}
-
-/* return number of events available in prioq */
-int snd_seq_prioq_avail(struct snd_seq_prioq * f)
-{
- if (f == NULL) {
- snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n");
- return 0;
- }
- return f->cells;
-}
-
-
-/* peek at cell at the head of the prioq */
-struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq * f)
-{
- if (f == NULL) {
- snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n");
- return NULL;
- }
- return f->head;
-}
-
-
-static inline int prioq_match(struct snd_seq_event_cell *cell,
- int client, int timestamp)
-{
- if (cell->event.source.client == client ||
- cell->event.dest.client == client)
- return 1;
- if (!timestamp)
- return 0;
- switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) {
- case SNDRV_SEQ_TIME_STAMP_TICK:
- if (cell->event.time.tick)
- return 1;
- break;
- case SNDRV_SEQ_TIME_STAMP_REAL:
- if (cell->event.time.time.tv_sec ||
- cell->event.time.time.tv_nsec)
- return 1;
- break;
- }
- return 0;
-}
-
-/* remove cells for left client */
-void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp)
-{
- register struct snd_seq_event_cell *cell, *next;
- unsigned long flags;
- struct snd_seq_event_cell *prev = NULL;
- struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext;
-
- /* collect all removed cells */
- spin_lock_irqsave(&f->lock, flags);
- cell = f->head;
- while (cell) {
- next = cell->next;
- if (prioq_match(cell, client, timestamp)) {
- /* remove cell from prioq */
- if (cell == f->head) {
- f->head = cell->next;
- } else {
- prev->next = cell->next;
- }
- if (cell == f->tail)
- f->tail = cell->next;
- f->cells--;
- /* add cell to free list */
- cell->next = NULL;
- if (freefirst == NULL) {
- freefirst = cell;
- } else {
- freeprev->next = cell;
- }
- freeprev = cell;
- } else {
-#if 0
- printk(KERN_DEBUG "type = %i, source = %i, dest = %i, "
- "client = %i\n",
- cell->event.type,
- cell->event.source.client,
- cell->event.dest.client,
- client);
-#endif
- prev = cell;
- }
- cell = next;
- }
- spin_unlock_irqrestore(&f->lock, flags);
-
- /* remove selected cells */
- while (freefirst) {
- freenext = freefirst->next;
- snd_seq_cell_free(freefirst);
- freefirst = freenext;
- }
-}
-
-static int prioq_remove_match(struct snd_seq_remove_events *info,
- struct snd_seq_event *ev)
-{
- int res;
-
- if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) {
- if (ev->dest.client != info->dest.client ||
- ev->dest.port != info->dest.port)
- return 0;
- }
- if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) {
- if (! snd_seq_ev_is_channel_type(ev))
- return 0;
- /* data.note.channel and data.control.channel are identical */
- if (ev->data.note.channel != info->channel)
- return 0;
- }
- if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) {
- if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
- res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
- else
- res = snd_seq_compare_real_time(&ev->time.time, &info->time.time);
- if (!res)
- return 0;
- }
- if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) {
- if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
- res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
- else
- res = snd_seq_compare_real_time(&ev->time.time, &info->time.time);
- if (res)
- return 0;
- }
- if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) {
- if (ev->type != info->type)
- return 0;
- }
- if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) {
- /* Do not remove off events */
- switch (ev->type) {
- case SNDRV_SEQ_EVENT_NOTEOFF:
- /* case SNDRV_SEQ_EVENT_SAMPLE_STOP: */
- return 0;
- default:
- break;
- }
- }
- if (info->remove_mode & SNDRV_SEQ_REMOVE_TAG_MATCH) {
- if (info->tag != ev->tag)
- return 0;
- }
-
- return 1;
-}
-
-/* remove cells matching remove criteria */
-void snd_seq_prioq_remove_events(struct snd_seq_prioq * f, int client,
- struct snd_seq_remove_events *info)
-{
- struct snd_seq_event_cell *cell, *next;
- unsigned long flags;
- struct snd_seq_event_cell *prev = NULL;
- struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext;
-
- /* collect all removed cells */
- spin_lock_irqsave(&f->lock, flags);
- cell = f->head;
-
- while (cell) {
- next = cell->next;
- if (cell->event.source.client == client &&
- prioq_remove_match(info, &cell->event)) {
-
- /* remove cell from prioq */
- if (cell == f->head) {
- f->head = cell->next;
- } else {
- prev->next = cell->next;
- }
-
- if (cell == f->tail)
- f->tail = cell->next;
- f->cells--;
-
- /* add cell to free list */
- cell->next = NULL;
- if (freefirst == NULL) {
- freefirst = cell;
- } else {
- freeprev->next = cell;
- }
-
- freeprev = cell;
- } else {
- prev = cell;
- }
- cell = next;
- }
- spin_unlock_irqrestore(&f->lock, flags);
-
- /* remove selected cells */
- while (freefirst) {
- freenext = freefirst->next;
- snd_seq_cell_free(freefirst);
- freefirst = freenext;
- }
-}
-
-
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_prioq.h b/ANDROID_3.4.5/sound/core/seq/seq_prioq.h
deleted file mode 100644
index d38bb78d..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_prioq.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * ALSA sequencer Priority Queue
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __SND_SEQ_PRIOQ_H
-#define __SND_SEQ_PRIOQ_H
-
-#include "seq_memory.h"
-
-
-/* === PRIOQ === */
-
-struct snd_seq_prioq {
- struct snd_seq_event_cell *head; /* pointer to head of prioq */
- struct snd_seq_event_cell *tail; /* pointer to tail of prioq */
- int cells;
- spinlock_t lock;
-};
-
-
-/* create new prioq (constructor) */
-struct snd_seq_prioq *snd_seq_prioq_new(void);
-
-/* delete prioq (destructor) */
-void snd_seq_prioq_delete(struct snd_seq_prioq **fifo);
-
-/* enqueue cell to prioq */
-int snd_seq_prioq_cell_in(struct snd_seq_prioq *f, struct snd_seq_event_cell *cell);
-
-/* dequeue cell from prioq */
-struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f);
-
-/* return number of events available in prioq */
-int snd_seq_prioq_avail(struct snd_seq_prioq *f);
-
-/* peek at cell at the head of the prioq */
-struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq *f);
-
-/* client left queue */
-void snd_seq_prioq_leave(struct snd_seq_prioq *f, int client, int timestamp);
-
-/* Remove events */
-void snd_seq_prioq_remove_events(struct snd_seq_prioq *f, int client,
- struct snd_seq_remove_events *info);
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_queue.c b/ANDROID_3.4.5/sound/core/seq/seq_queue.c
deleted file mode 100644
index f9077361..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_queue.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * ALSA sequencer Timing queue handling
- * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * MAJOR CHANGES
- * Nov. 13, 1999 Takashi Iwai <iwai@ww.uni-erlangen.de>
- * - Queues are allocated dynamically via ioctl.
- * - When owner client is deleted, all owned queues are deleted, too.
- * - Owner of unlocked queue is kept unmodified even if it is
- * manipulated by other clients.
- * - Owner field in SET_QUEUE_OWNER ioctl must be identical with the
- * caller client. i.e. Changing owner to a third client is not
- * allowed.
- *
- * Aug. 30, 2000 Takashi Iwai
- * - Queues are managed in static array again, but with better way.
- * The API itself is identical.
- * - The queue is locked when struct snd_seq_queue pointer is returned via
- * queueptr(). This pointer *MUST* be released afterward by
- * queuefree(ptr).
- * - Addition of experimental sync support.
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-
-#include "seq_memory.h"
-#include "seq_queue.h"
-#include "seq_clientmgr.h"
-#include "seq_fifo.h"
-#include "seq_timer.h"
-#include "seq_info.h"
-
-/* list of allocated queues */
-static struct snd_seq_queue *queue_list[SNDRV_SEQ_MAX_QUEUES];
-static DEFINE_SPINLOCK(queue_list_lock);
-/* number of queues allocated */
-static int num_queues;
-
-int snd_seq_queue_get_cur_queues(void)
-{
- return num_queues;
-}
-
-/*----------------------------------------------------------------*/
-
-/* assign queue id and insert to list */
-static int queue_list_add(struct snd_seq_queue *q)
-{
- int i;
- unsigned long flags;
-
- spin_lock_irqsave(&queue_list_lock, flags);
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if (! queue_list[i]) {
- queue_list[i] = q;
- q->queue = i;
- num_queues++;
- spin_unlock_irqrestore(&queue_list_lock, flags);
- return i;
- }
- }
- spin_unlock_irqrestore(&queue_list_lock, flags);
- return -1;
-}
-
-static struct snd_seq_queue *queue_list_remove(int id, int client)
-{
- struct snd_seq_queue *q;
- unsigned long flags;
-
- spin_lock_irqsave(&queue_list_lock, flags);
- q = queue_list[id];
- if (q) {
- spin_lock(&q->owner_lock);
- if (q->owner == client) {
- /* found */
- q->klocked = 1;
- spin_unlock(&q->owner_lock);
- queue_list[id] = NULL;
- num_queues--;
- spin_unlock_irqrestore(&queue_list_lock, flags);
- return q;
- }
- spin_unlock(&q->owner_lock);
- }
- spin_unlock_irqrestore(&queue_list_lock, flags);
- return NULL;
-}
-
-/*----------------------------------------------------------------*/
-
-/* create new queue (constructor) */
-static struct snd_seq_queue *queue_new(int owner, int locked)
-{
- struct snd_seq_queue *q;
-
- q = kzalloc(sizeof(*q), GFP_KERNEL);
- if (q == NULL) {
- snd_printd("malloc failed for snd_seq_queue_new()\n");
- return NULL;
- }
-
- spin_lock_init(&q->owner_lock);
- spin_lock_init(&q->check_lock);
- mutex_init(&q->timer_mutex);
- snd_use_lock_init(&q->use_lock);
- q->queue = -1;
-
- q->tickq = snd_seq_prioq_new();
- q->timeq = snd_seq_prioq_new();
- q->timer = snd_seq_timer_new();
- if (q->tickq == NULL || q->timeq == NULL || q->timer == NULL) {
- snd_seq_prioq_delete(&q->tickq);
- snd_seq_prioq_delete(&q->timeq);
- snd_seq_timer_delete(&q->timer);
- kfree(q);
- return NULL;
- }
-
- q->owner = owner;
- q->locked = locked;
- q->klocked = 0;
-
- return q;
-}
-
-/* delete queue (destructor) */
-static void queue_delete(struct snd_seq_queue *q)
-{
- /* stop and release the timer */
- snd_seq_timer_stop(q->timer);
- snd_seq_timer_close(q);
- /* wait until access free */
- snd_use_lock_sync(&q->use_lock);
- /* release resources... */
- snd_seq_prioq_delete(&q->tickq);
- snd_seq_prioq_delete(&q->timeq);
- snd_seq_timer_delete(&q->timer);
-
- kfree(q);
-}
-
-
-/*----------------------------------------------------------------*/
-
-/* setup queues */
-int __init snd_seq_queues_init(void)
-{
- /*
- memset(queue_list, 0, sizeof(queue_list));
- num_queues = 0;
- */
- return 0;
-}
-
-/* delete all existing queues */
-void __exit snd_seq_queues_delete(void)
-{
- int i;
-
- /* clear list */
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if (queue_list[i])
- queue_delete(queue_list[i]);
- }
-}
-
-/* allocate a new queue -
- * return queue index value or negative value for error
- */
-int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags)
-{
- struct snd_seq_queue *q;
-
- q = queue_new(client, locked);
- if (q == NULL)
- return -ENOMEM;
- q->info_flags = info_flags;
- if (queue_list_add(q) < 0) {
- queue_delete(q);
- return -ENOMEM;
- }
- snd_seq_queue_use(q->queue, client, 1); /* use this queue */
- return q->queue;
-}
-
-/* delete a queue - queue must be owned by the client */
-int snd_seq_queue_delete(int client, int queueid)
-{
- struct snd_seq_queue *q;
-
- if (queueid < 0 || queueid >= SNDRV_SEQ_MAX_QUEUES)
- return -EINVAL;
- q = queue_list_remove(queueid, client);
- if (q == NULL)
- return -EINVAL;
- queue_delete(q);
-
- return 0;
-}
-
-
-/* return pointer to queue structure for specified id */
-struct snd_seq_queue *queueptr(int queueid)
-{
- struct snd_seq_queue *q;
- unsigned long flags;
-
- if (queueid < 0 || queueid >= SNDRV_SEQ_MAX_QUEUES)
- return NULL;
- spin_lock_irqsave(&queue_list_lock, flags);
- q = queue_list[queueid];
- if (q)
- snd_use_lock_use(&q->use_lock);
- spin_unlock_irqrestore(&queue_list_lock, flags);
- return q;
-}
-
-/* return the (first) queue matching with the specified name */
-struct snd_seq_queue *snd_seq_queue_find_name(char *name)
-{
- int i;
- struct snd_seq_queue *q;
-
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if ((q = queueptr(i)) != NULL) {
- if (strncmp(q->name, name, sizeof(q->name)) == 0)
- return q;
- queuefree(q);
- }
- }
- return NULL;
-}
-
-
-/* -------------------------------------------------------- */
-
-void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
-{
- unsigned long flags;
- struct snd_seq_event_cell *cell;
-
- if (q == NULL)
- return;
-
- /* make this function non-reentrant */
- spin_lock_irqsave(&q->check_lock, flags);
- if (q->check_blocked) {
- q->check_again = 1;
- spin_unlock_irqrestore(&q->check_lock, flags);
- return; /* other thread is already checking queues */
- }
- q->check_blocked = 1;
- spin_unlock_irqrestore(&q->check_lock, flags);
-
- __again:
- /* Process tick queue... */
- while ((cell = snd_seq_prioq_cell_peek(q->tickq)) != NULL) {
- if (snd_seq_compare_tick_time(&q->timer->tick.cur_tick,
- &cell->event.time.tick)) {
- cell = snd_seq_prioq_cell_out(q->tickq);
- if (cell)
- snd_seq_dispatch_event(cell, atomic, hop);
- } else {
- /* event remains in the queue */
- break;
- }
- }
-
-
- /* Process time queue... */
- while ((cell = snd_seq_prioq_cell_peek(q->timeq)) != NULL) {
- if (snd_seq_compare_real_time(&q->timer->cur_time,
- &cell->event.time.time)) {
- cell = snd_seq_prioq_cell_out(q->timeq);
- if (cell)
- snd_seq_dispatch_event(cell, atomic, hop);
- } else {
- /* event remains in the queue */
- break;
- }
- }
-
- /* free lock */
- spin_lock_irqsave(&q->check_lock, flags);
- if (q->check_again) {
- q->check_again = 0;
- spin_unlock_irqrestore(&q->check_lock, flags);
- goto __again;
- }
- q->check_blocked = 0;
- spin_unlock_irqrestore(&q->check_lock, flags);
-}
-
-
-/* enqueue a event to singe queue */
-int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop)
-{
- int dest, err;
- struct snd_seq_queue *q;
-
- if (snd_BUG_ON(!cell))
- return -EINVAL;
- dest = cell->event.queue; /* destination queue */
- q = queueptr(dest);
- if (q == NULL)
- return -EINVAL;
- /* handle relative time stamps, convert them into absolute */
- if ((cell->event.flags & SNDRV_SEQ_TIME_MODE_MASK) == SNDRV_SEQ_TIME_MODE_REL) {
- switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) {
- case SNDRV_SEQ_TIME_STAMP_TICK:
- cell->event.time.tick += q->timer->tick.cur_tick;
- break;
-
- case SNDRV_SEQ_TIME_STAMP_REAL:
- snd_seq_inc_real_time(&cell->event.time.time,
- &q->timer->cur_time);
- break;
- }
- cell->event.flags &= ~SNDRV_SEQ_TIME_MODE_MASK;
- cell->event.flags |= SNDRV_SEQ_TIME_MODE_ABS;
- }
- /* enqueue event in the real-time or midi queue */
- switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) {
- case SNDRV_SEQ_TIME_STAMP_TICK:
- err = snd_seq_prioq_cell_in(q->tickq, cell);
- break;
-
- case SNDRV_SEQ_TIME_STAMP_REAL:
- default:
- err = snd_seq_prioq_cell_in(q->timeq, cell);
- break;
- }
-
- if (err < 0) {
- queuefree(q); /* unlock */
- return err;
- }
-
- /* trigger dispatching */
- snd_seq_check_queue(q, atomic, hop);
-
- queuefree(q); /* unlock */
-
- return 0;
-}
-
-
-/*----------------------------------------------------------------*/
-
-static inline int check_access(struct snd_seq_queue *q, int client)
-{
- return (q->owner == client) || (!q->locked && !q->klocked);
-}
-
-/* check if the client has permission to modify queue parameters.
- * if it does, lock the queue
- */
-static int queue_access_lock(struct snd_seq_queue *q, int client)
-{
- unsigned long flags;
- int access_ok;
-
- spin_lock_irqsave(&q->owner_lock, flags);
- access_ok = check_access(q, client);
- if (access_ok)
- q->klocked = 1;
- spin_unlock_irqrestore(&q->owner_lock, flags);
- return access_ok;
-}
-
-/* unlock the queue */
-static inline void queue_access_unlock(struct snd_seq_queue *q)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&q->owner_lock, flags);
- q->klocked = 0;
- spin_unlock_irqrestore(&q->owner_lock, flags);
-}
-
-/* exported - only checking permission */
-int snd_seq_queue_check_access(int queueid, int client)
-{
- struct snd_seq_queue *q = queueptr(queueid);
- int access_ok;
- unsigned long flags;
-
- if (! q)
- return 0;
- spin_lock_irqsave(&q->owner_lock, flags);
- access_ok = check_access(q, client);
- spin_unlock_irqrestore(&q->owner_lock, flags);
- queuefree(q);
- return access_ok;
-}
-
-/*----------------------------------------------------------------*/
-
-/*
- * change queue's owner and permission
- */
-int snd_seq_queue_set_owner(int queueid, int client, int locked)
-{
- struct snd_seq_queue *q = queueptr(queueid);
-
- if (q == NULL)
- return -EINVAL;
-
- if (! queue_access_lock(q, client)) {
- queuefree(q);
- return -EPERM;
- }
-
- q->locked = locked ? 1 : 0;
- q->owner = client;
- queue_access_unlock(q);
- queuefree(q);
-
- return 0;
-}
-
-
-/*----------------------------------------------------------------*/
-
-/* open timer -
- * q->use mutex should be down before calling this function to avoid
- * confliction with snd_seq_queue_use()
- */
-int snd_seq_queue_timer_open(int queueid)
-{
- int result = 0;
- struct snd_seq_queue *queue;
- struct snd_seq_timer *tmr;
-
- queue = queueptr(queueid);
- if (queue == NULL)
- return -EINVAL;
- tmr = queue->timer;
- if ((result = snd_seq_timer_open(queue)) < 0) {
- snd_seq_timer_defaults(tmr);
- result = snd_seq_timer_open(queue);
- }
- queuefree(queue);
- return result;
-}
-
-/* close timer -
- * q->use mutex should be down before calling this function
- */
-int snd_seq_queue_timer_close(int queueid)
-{
- struct snd_seq_queue *queue;
- int result = 0;
-
- queue = queueptr(queueid);
- if (queue == NULL)
- return -EINVAL;
- snd_seq_timer_close(queue);
- queuefree(queue);
- return result;
-}
-
-/* change queue tempo and ppq */
-int snd_seq_queue_timer_set_tempo(int queueid, int client,
- struct snd_seq_queue_tempo *info)
-{
- struct snd_seq_queue *q = queueptr(queueid);
- int result;
-
- if (q == NULL)
- return -EINVAL;
- if (! queue_access_lock(q, client)) {
- queuefree(q);
- return -EPERM;
- }
-
- result = snd_seq_timer_set_tempo(q->timer, info->tempo);
- if (result >= 0)
- result = snd_seq_timer_set_ppq(q->timer, info->ppq);
- if (result >= 0 && info->skew_base > 0)
- result = snd_seq_timer_set_skew(q->timer, info->skew_value,
- info->skew_base);
- queue_access_unlock(q);
- queuefree(q);
- return result;
-}
-
-
-/* use or unuse this queue -
- * if it is the first client, starts the timer.
- * if it is not longer used by any clients, stop the timer.
- */
-int snd_seq_queue_use(int queueid, int client, int use)
-{
- struct snd_seq_queue *queue;
-
- queue = queueptr(queueid);
- if (queue == NULL)
- return -EINVAL;
- mutex_lock(&queue->timer_mutex);
- if (use) {
- if (!test_and_set_bit(client, queue->clients_bitmap))
- queue->clients++;
- } else {
- if (test_and_clear_bit(client, queue->clients_bitmap))
- queue->clients--;
- }
- if (queue->clients) {
- if (use && queue->clients == 1)
- snd_seq_timer_defaults(queue->timer);
- snd_seq_timer_open(queue);
- } else {
- snd_seq_timer_close(queue);
- }
- mutex_unlock(&queue->timer_mutex);
- queuefree(queue);
- return 0;
-}
-
-/*
- * check if queue is used by the client
- * return negative value if the queue is invalid.
- * return 0 if not used, 1 if used.
- */
-int snd_seq_queue_is_used(int queueid, int client)
-{
- struct snd_seq_queue *q;
- int result;
-
- q = queueptr(queueid);
- if (q == NULL)
- return -EINVAL; /* invalid queue */
- result = test_bit(client, q->clients_bitmap) ? 1 : 0;
- queuefree(q);
- return result;
-}
-
-
-/*----------------------------------------------------------------*/
-
-/* notification that client has left the system -
- * stop the timer on all queues owned by this client
- */
-void snd_seq_queue_client_termination(int client)
-{
- unsigned long flags;
- int i;
- struct snd_seq_queue *q;
-
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if ((q = queueptr(i)) == NULL)
- continue;
- spin_lock_irqsave(&q->owner_lock, flags);
- if (q->owner == client)
- q->klocked = 1;
- spin_unlock_irqrestore(&q->owner_lock, flags);
- if (q->owner == client) {
- if (q->timer->running)
- snd_seq_timer_stop(q->timer);
- snd_seq_timer_reset(q->timer);
- }
- queuefree(q);
- }
-}
-
-/* final stage notification -
- * remove cells for no longer exist client (for non-owned queue)
- * or delete this queue (for owned queue)
- */
-void snd_seq_queue_client_leave(int client)
-{
- int i;
- struct snd_seq_queue *q;
-
- /* delete own queues from queue list */
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if ((q = queue_list_remove(i, client)) != NULL)
- queue_delete(q);
- }
-
- /* remove cells from existing queues -
- * they are not owned by this client
- */
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if ((q = queueptr(i)) == NULL)
- continue;
- if (test_bit(client, q->clients_bitmap)) {
- snd_seq_prioq_leave(q->tickq, client, 0);
- snd_seq_prioq_leave(q->timeq, client, 0);
- snd_seq_queue_use(q->queue, client, 0);
- }
- queuefree(q);
- }
-}
-
-
-
-/*----------------------------------------------------------------*/
-
-/* remove cells from all queues */
-void snd_seq_queue_client_leave_cells(int client)
-{
- int i;
- struct snd_seq_queue *q;
-
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if ((q = queueptr(i)) == NULL)
- continue;
- snd_seq_prioq_leave(q->tickq, client, 0);
- snd_seq_prioq_leave(q->timeq, client, 0);
- queuefree(q);
- }
-}
-
-/* remove cells based on flush criteria */
-void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info)
-{
- int i;
- struct snd_seq_queue *q;
-
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if ((q = queueptr(i)) == NULL)
- continue;
- if (test_bit(client, q->clients_bitmap) &&
- (! (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) ||
- q->queue == info->queue)) {
- snd_seq_prioq_remove_events(q->tickq, client, info);
- snd_seq_prioq_remove_events(q->timeq, client, info);
- }
- queuefree(q);
- }
-}
-
-/*----------------------------------------------------------------*/
-
-/*
- * send events to all subscribed ports
- */
-static void queue_broadcast_event(struct snd_seq_queue *q, struct snd_seq_event *ev,
- int atomic, int hop)
-{
- struct snd_seq_event sev;
-
- sev = *ev;
-
- sev.flags = SNDRV_SEQ_TIME_STAMP_TICK|SNDRV_SEQ_TIME_MODE_ABS;
- sev.time.tick = q->timer->tick.cur_tick;
- sev.queue = q->queue;
- sev.data.queue.queue = q->queue;
-
- /* broadcast events from Timer port */
- sev.source.client = SNDRV_SEQ_CLIENT_SYSTEM;
- sev.source.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
- sev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- snd_seq_kernel_client_dispatch(SNDRV_SEQ_CLIENT_SYSTEM, &sev, atomic, hop);
-}
-
-/*
- * process a received queue-control event.
- * this function is exported for seq_sync.c.
- */
-static void snd_seq_queue_process_event(struct snd_seq_queue *q,
- struct snd_seq_event *ev,
- int atomic, int hop)
-{
- switch (ev->type) {
- case SNDRV_SEQ_EVENT_START:
- snd_seq_prioq_leave(q->tickq, ev->source.client, 1);
- snd_seq_prioq_leave(q->timeq, ev->source.client, 1);
- if (! snd_seq_timer_start(q->timer))
- queue_broadcast_event(q, ev, atomic, hop);
- break;
-
- case SNDRV_SEQ_EVENT_CONTINUE:
- if (! snd_seq_timer_continue(q->timer))
- queue_broadcast_event(q, ev, atomic, hop);
- break;
-
- case SNDRV_SEQ_EVENT_STOP:
- snd_seq_timer_stop(q->timer);
- queue_broadcast_event(q, ev, atomic, hop);
- break;
-
- case SNDRV_SEQ_EVENT_TEMPO:
- snd_seq_timer_set_tempo(q->timer, ev->data.queue.param.value);
- queue_broadcast_event(q, ev, atomic, hop);
- break;
-
- case SNDRV_SEQ_EVENT_SETPOS_TICK:
- if (snd_seq_timer_set_position_tick(q->timer, ev->data.queue.param.time.tick) == 0) {
- queue_broadcast_event(q, ev, atomic, hop);
- }
- break;
-
- case SNDRV_SEQ_EVENT_SETPOS_TIME:
- if (snd_seq_timer_set_position_time(q->timer, ev->data.queue.param.time.time) == 0) {
- queue_broadcast_event(q, ev, atomic, hop);
- }
- break;
- case SNDRV_SEQ_EVENT_QUEUE_SKEW:
- if (snd_seq_timer_set_skew(q->timer,
- ev->data.queue.param.skew.value,
- ev->data.queue.param.skew.base) == 0) {
- queue_broadcast_event(q, ev, atomic, hop);
- }
- break;
- }
-}
-
-
-/*
- * Queue control via timer control port:
- * this function is exported as a callback of timer port.
- */
-int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop)
-{
- struct snd_seq_queue *q;
-
- if (snd_BUG_ON(!ev))
- return -EINVAL;
- q = queueptr(ev->data.queue.queue);
-
- if (q == NULL)
- return -EINVAL;
-
- if (! queue_access_lock(q, ev->source.client)) {
- queuefree(q);
- return -EPERM;
- }
-
- snd_seq_queue_process_event(q, ev, atomic, hop);
-
- queue_access_unlock(q);
- queuefree(q);
- return 0;
-}
-
-
-/*----------------------------------------------------------------*/
-
-#ifdef CONFIG_PROC_FS
-/* exported to seq_info.c */
-void snd_seq_info_queues_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- int i, bpm;
- struct snd_seq_queue *q;
- struct snd_seq_timer *tmr;
-
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if ((q = queueptr(i)) == NULL)
- continue;
-
- tmr = q->timer;
- if (tmr->tempo)
- bpm = 60000000 / tmr->tempo;
- else
- bpm = 0;
-
- snd_iprintf(buffer, "queue %d: [%s]\n", q->queue, q->name);
- snd_iprintf(buffer, "owned by client : %d\n", q->owner);
- snd_iprintf(buffer, "lock status : %s\n", q->locked ? "Locked" : "Free");
- snd_iprintf(buffer, "queued time events : %d\n", snd_seq_prioq_avail(q->timeq));
- snd_iprintf(buffer, "queued tick events : %d\n", snd_seq_prioq_avail(q->tickq));
- snd_iprintf(buffer, "timer state : %s\n", tmr->running ? "Running" : "Stopped");
- snd_iprintf(buffer, "timer PPQ : %d\n", tmr->ppq);
- snd_iprintf(buffer, "current tempo : %d\n", tmr->tempo);
- snd_iprintf(buffer, "current BPM : %d\n", bpm);
- snd_iprintf(buffer, "current time : %d.%09d s\n", tmr->cur_time.tv_sec, tmr->cur_time.tv_nsec);
- snd_iprintf(buffer, "current tick : %d\n", tmr->tick.cur_tick);
- snd_iprintf(buffer, "\n");
- queuefree(q);
- }
-}
-#endif /* CONFIG_PROC_FS */
-
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_queue.h b/ANDROID_3.4.5/sound/core/seq/seq_queue.h
deleted file mode 100644
index 30c81114..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_queue.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * ALSA sequencer Queue handling
- * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __SND_SEQ_QUEUE_H
-#define __SND_SEQ_QUEUE_H
-
-#include "seq_memory.h"
-#include "seq_prioq.h"
-#include "seq_timer.h"
-#include "seq_lock.h"
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-
-#define SEQ_QUEUE_NO_OWNER (-1)
-
-struct snd_seq_queue {
- int queue; /* queue number */
-
- char name[64]; /* name of this queue */
-
- struct snd_seq_prioq *tickq; /* midi tick event queue */
- struct snd_seq_prioq *timeq; /* real-time event queue */
-
- struct snd_seq_timer *timer; /* time keeper for this queue */
- int owner; /* client that 'owns' the timer */
- unsigned int locked:1, /* timer is only accesibble by owner if set */
- klocked:1, /* kernel lock (after START) */
- check_again:1,
- check_blocked:1;
-
- unsigned int flags; /* status flags */
- unsigned int info_flags; /* info for sync */
-
- spinlock_t owner_lock;
- spinlock_t check_lock;
-
- /* clients which uses this queue (bitmap) */
- DECLARE_BITMAP(clients_bitmap, SNDRV_SEQ_MAX_CLIENTS);
- unsigned int clients; /* users of this queue */
- struct mutex timer_mutex;
-
- snd_use_lock_t use_lock;
-};
-
-
-/* get the number of current queues */
-int snd_seq_queue_get_cur_queues(void);
-
-/* init queues structure */
-int snd_seq_queues_init(void);
-
-/* delete queues */
-void snd_seq_queues_delete(void);
-
-
-/* create new queue (constructor) */
-int snd_seq_queue_alloc(int client, int locked, unsigned int flags);
-
-/* delete queue (destructor) */
-int snd_seq_queue_delete(int client, int queueid);
-
-/* notification that client has left the system */
-void snd_seq_queue_client_termination(int client);
-
-/* final stage */
-void snd_seq_queue_client_leave(int client);
-
-/* enqueue a event received from one the clients */
-int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop);
-
-/* Remove events */
-void snd_seq_queue_client_leave_cells(int client);
-void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info);
-
-/* return pointer to queue structure for specified id */
-struct snd_seq_queue *queueptr(int queueid);
-/* unlock */
-#define queuefree(q) snd_use_lock_free(&(q)->use_lock)
-
-/* return the (first) queue matching with the specified name */
-struct snd_seq_queue *snd_seq_queue_find_name(char *name);
-
-/* check single queue and dispatch events */
-void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop);
-
-/* access to queue's parameters */
-int snd_seq_queue_check_access(int queueid, int client);
-int snd_seq_queue_timer_set_tempo(int queueid, int client, struct snd_seq_queue_tempo *info);
-int snd_seq_queue_set_owner(int queueid, int client, int locked);
-int snd_seq_queue_set_locked(int queueid, int client, int locked);
-int snd_seq_queue_timer_open(int queueid);
-int snd_seq_queue_timer_close(int queueid);
-int snd_seq_queue_use(int queueid, int client, int use);
-int snd_seq_queue_is_used(int queueid, int client);
-
-int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop);
-
-/*
- * 64bit division - for sync stuff..
- */
-#if defined(i386) || defined(i486)
-
-#define udiv_qrnnd(q, r, n1, n0, d) \
- __asm__ ("divl %4" \
- : "=a" ((u32)(q)), \
- "=d" ((u32)(r)) \
- : "0" ((u32)(n0)), \
- "1" ((u32)(n1)), \
- "rm" ((u32)(d)))
-
-#define u64_div(x,y,q) do {u32 __tmp; udiv_qrnnd(q, __tmp, (x)>>32, x, y);} while (0)
-#define u64_mod(x,y,r) do {u32 __tmp; udiv_qrnnd(__tmp, q, (x)>>32, x, y);} while (0)
-#define u64_divmod(x,y,q,r) udiv_qrnnd(q, r, (x)>>32, x, y)
-
-#else
-#define u64_div(x,y,q) ((q) = (u32)((u64)(x) / (u64)(y)))
-#define u64_mod(x,y,r) ((r) = (u32)((u64)(x) % (u64)(y)))
-#define u64_divmod(x,y,q,r) (u64_div(x,y,q), u64_mod(x,y,r))
-#endif
-
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_system.c b/ANDROID_3.4.5/sound/core/seq/seq_system.c
deleted file mode 100644
index 8ce1d0b4..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_system.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * ALSA sequencer System services Client
- * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include "seq_system.h"
-#include "seq_timer.h"
-#include "seq_queue.h"
-
-/* internal client that provide system services, access to timer etc. */
-
-/*
- * Port "Timer"
- * - send tempo /start/stop etc. events to this port to manipulate the
- * queue's timer. The queue address is specified in
- * data.queue.queue.
- * - this port supports subscription. The received timer events are
- * broadcasted to all subscribed clients. The modified tempo
- * value is stored on data.queue.value.
- * The modifier client/port is not send.
- *
- * Port "Announce"
- * - does not receive message
- * - supports supscription. For each client or port attaching to or
- * detaching from the system an announcement is send to the subscribed
- * clients.
- *
- * Idea: the subscription mechanism might also work handy for distributing
- * synchronisation and timing information. In this case we would ideally have
- * a list of subscribers for each type of sync (time, tick), for each timing
- * queue.
- *
- * NOTE: the queue to be started, stopped, etc. must be specified
- * in data.queue.addr.queue field. queue is used only for
- * scheduling, and no longer referred as affected queue.
- * They are used only for timer broadcast (see above).
- * -- iwai
- */
-
-
-/* client id of our system client */
-static int sysclient = -1;
-
-/* port id numbers for this client */
-static int announce_port = -1;
-
-
-
-/* fill standard header data, source port & channel are filled in */
-static int setheader(struct snd_seq_event * ev, int client, int port)
-{
- if (announce_port < 0)
- return -ENODEV;
-
- memset(ev, 0, sizeof(struct snd_seq_event));
-
- ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
- ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
-
- ev->source.client = sysclient;
- ev->source.port = announce_port;
- ev->dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
-
- /* fill data */
- /*ev->data.addr.queue = SNDRV_SEQ_ADDRESS_UNKNOWN;*/
- ev->data.addr.client = client;
- ev->data.addr.port = port;
-
- return 0;
-}
-
-
-/* entry points for broadcasting system events */
-void snd_seq_system_broadcast(int client, int port, int type)
-{
- struct snd_seq_event ev;
-
- if (setheader(&ev, client, port) < 0)
- return;
- ev.type = type;
- snd_seq_kernel_client_dispatch(sysclient, &ev, 0, 0);
-}
-
-/* entry points for broadcasting system events */
-int snd_seq_system_notify(int client, int port, struct snd_seq_event *ev)
-{
- ev->flags = SNDRV_SEQ_EVENT_LENGTH_FIXED;
- ev->source.client = sysclient;
- ev->source.port = announce_port;
- ev->dest.client = client;
- ev->dest.port = port;
- return snd_seq_kernel_client_dispatch(sysclient, ev, 0, 0);
-}
-
-/* call-back handler for timer events */
-static int event_input_timer(struct snd_seq_event * ev, int direct, void *private_data, int atomic, int hop)
-{
- return snd_seq_control_queue(ev, atomic, hop);
-}
-
-/* register our internal client */
-int __init snd_seq_system_client_init(void)
-{
- struct snd_seq_port_callback pcallbacks;
- struct snd_seq_port_info *port;
-
- port = kzalloc(sizeof(*port), GFP_KERNEL);
- if (!port)
- return -ENOMEM;
-
- memset(&pcallbacks, 0, sizeof(pcallbacks));
- pcallbacks.owner = THIS_MODULE;
- pcallbacks.event_input = event_input_timer;
-
- /* register client */
- sysclient = snd_seq_create_kernel_client(NULL, 0, "System");
-
- /* register timer */
- strcpy(port->name, "Timer");
- port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* accept queue control */
- port->capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast */
- port->kernel = &pcallbacks;
- port->type = 0;
- port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
- port->addr.client = sysclient;
- port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
- snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
-
- /* register announcement port */
- strcpy(port->name, "Announce");
- port->capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast only */
- port->kernel = NULL;
- port->type = 0;
- port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
- port->addr.client = sysclient;
- port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
- snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
- announce_port = port->addr.port;
-
- kfree(port);
- return 0;
-}
-
-
-/* unregister our internal client */
-void __exit snd_seq_system_client_done(void)
-{
- int oldsysclient = sysclient;
-
- if (oldsysclient >= 0) {
- sysclient = -1;
- announce_port = -1;
- snd_seq_delete_kernel_client(oldsysclient);
- }
-}
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_system.h b/ANDROID_3.4.5/sound/core/seq/seq_system.h
deleted file mode 100644
index cf2cfa23..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_system.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * ALSA sequencer System Client
- * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __SND_SEQ_SYSTEM_H
-#define __SND_SEQ_SYSTEM_H
-
-#include <sound/seq_kernel.h>
-
-
-/* entry points for broadcasting system events */
-void snd_seq_system_broadcast(int client, int port, int type);
-
-#define snd_seq_system_client_ev_client_start(client) snd_seq_system_broadcast(client, 0, SNDRV_SEQ_EVENT_CLIENT_START)
-#define snd_seq_system_client_ev_client_exit(client) snd_seq_system_broadcast(client, 0, SNDRV_SEQ_EVENT_CLIENT_EXIT)
-#define snd_seq_system_client_ev_client_change(client) snd_seq_system_broadcast(client, 0, SNDRV_SEQ_EVENT_CLIENT_CHANGE)
-#define snd_seq_system_client_ev_port_start(client, port) snd_seq_system_broadcast(client, port, SNDRV_SEQ_EVENT_PORT_START)
-#define snd_seq_system_client_ev_port_exit(client, port) snd_seq_system_broadcast(client, port, SNDRV_SEQ_EVENT_PORT_EXIT)
-#define snd_seq_system_client_ev_port_change(client, port) snd_seq_system_broadcast(client, port, SNDRV_SEQ_EVENT_PORT_CHANGE)
-
-int snd_seq_system_notify(int client, int port, struct snd_seq_event *ev);
-
-/* register our internal client */
-int snd_seq_system_client_init(void);
-
-/* unregister our internal client */
-void snd_seq_system_client_done(void);
-
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_timer.c b/ANDROID_3.4.5/sound/core/seq/seq_timer.c
deleted file mode 100644
index 160b1bd0..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_timer.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * ALSA sequencer Timer
- * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <sound/core.h>
-#include <linux/slab.h>
-#include "seq_timer.h"
-#include "seq_queue.h"
-#include "seq_info.h"
-
-/* allowed sequencer timer frequencies, in Hz */
-#define MIN_FREQUENCY 10
-#define MAX_FREQUENCY 6250
-#define DEFAULT_FREQUENCY 1000
-
-#define SKEW_BASE 0x10000 /* 16bit shift */
-
-static void snd_seq_timer_set_tick_resolution(struct snd_seq_timer *tmr)
-{
- if (tmr->tempo < 1000000)
- tmr->tick.resolution = (tmr->tempo * 1000) / tmr->ppq;
- else {
- /* might overflow.. */
- unsigned int s;
- s = tmr->tempo % tmr->ppq;
- s = (s * 1000) / tmr->ppq;
- tmr->tick.resolution = (tmr->tempo / tmr->ppq) * 1000;
- tmr->tick.resolution += s;
- }
- if (tmr->tick.resolution <= 0)
- tmr->tick.resolution = 1;
- snd_seq_timer_update_tick(&tmr->tick, 0);
-}
-
-/* create new timer (constructor) */
-struct snd_seq_timer *snd_seq_timer_new(void)
-{
- struct snd_seq_timer *tmr;
-
- tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
- if (tmr == NULL) {
- snd_printd("malloc failed for snd_seq_timer_new() \n");
- return NULL;
- }
- spin_lock_init(&tmr->lock);
-
- /* reset setup to defaults */
- snd_seq_timer_defaults(tmr);
-
- /* reset time */
- snd_seq_timer_reset(tmr);
-
- return tmr;
-}
-
-/* delete timer (destructor) */
-void snd_seq_timer_delete(struct snd_seq_timer **tmr)
-{
- struct snd_seq_timer *t = *tmr;
- *tmr = NULL;
-
- if (t == NULL) {
- snd_printd("oops: snd_seq_timer_delete() called with NULL timer\n");
- return;
- }
- t->running = 0;
-
- /* reset time */
- snd_seq_timer_stop(t);
- snd_seq_timer_reset(t);
-
- kfree(t);
-}
-
-void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
-{
- /* setup defaults */
- tmr->ppq = 96; /* 96 PPQ */
- tmr->tempo = 500000; /* 120 BPM */
- snd_seq_timer_set_tick_resolution(tmr);
- tmr->running = 0;
-
- tmr->type = SNDRV_SEQ_TIMER_ALSA;
- tmr->alsa_id.dev_class = seq_default_timer_class;
- tmr->alsa_id.dev_sclass = seq_default_timer_sclass;
- tmr->alsa_id.card = seq_default_timer_card;
- tmr->alsa_id.device = seq_default_timer_device;
- tmr->alsa_id.subdevice = seq_default_timer_subdevice;
- tmr->preferred_resolution = seq_default_timer_resolution;
-
- tmr->skew = tmr->skew_base = SKEW_BASE;
-}
-
-void snd_seq_timer_reset(struct snd_seq_timer * tmr)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&tmr->lock, flags);
-
- /* reset time & songposition */
- tmr->cur_time.tv_sec = 0;
- tmr->cur_time.tv_nsec = 0;
-
- tmr->tick.cur_tick = 0;
- tmr->tick.fraction = 0;
-
- spin_unlock_irqrestore(&tmr->lock, flags);
-}
-
-
-/* called by timer interrupt routine. the period time since previous invocation is passed */
-static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
- unsigned long resolution,
- unsigned long ticks)
-{
- unsigned long flags;
- struct snd_seq_queue *q = timeri->callback_data;
- struct snd_seq_timer *tmr;
-
- if (q == NULL)
- return;
- tmr = q->timer;
- if (tmr == NULL)
- return;
- if (!tmr->running)
- return;
-
- resolution *= ticks;
- if (tmr->skew != tmr->skew_base) {
- /* FIXME: assuming skew_base = 0x10000 */
- resolution = (resolution >> 16) * tmr->skew +
- (((resolution & 0xffff) * tmr->skew) >> 16);
- }
-
- spin_lock_irqsave(&tmr->lock, flags);
-
- /* update timer */
- snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
-
- /* calculate current tick */
- snd_seq_timer_update_tick(&tmr->tick, resolution);
-
- /* register actual time of this timer update */
- do_gettimeofday(&tmr->last_update);
-
- spin_unlock_irqrestore(&tmr->lock, flags);
-
- /* check queues and dispatch events */
- snd_seq_check_queue(q, 1, 0);
-}
-
-/* set current tempo */
-int snd_seq_timer_set_tempo(struct snd_seq_timer * tmr, int tempo)
-{
- unsigned long flags;
-
- if (snd_BUG_ON(!tmr))
- return -EINVAL;
- if (tempo <= 0)
- return -EINVAL;
- spin_lock_irqsave(&tmr->lock, flags);
- if ((unsigned int)tempo != tmr->tempo) {
- tmr->tempo = tempo;
- snd_seq_timer_set_tick_resolution(tmr);
- }
- spin_unlock_irqrestore(&tmr->lock, flags);
- return 0;
-}
-
-/* set current ppq */
-int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq)
-{
- unsigned long flags;
-
- if (snd_BUG_ON(!tmr))
- return -EINVAL;
- if (ppq <= 0)
- return -EINVAL;
- spin_lock_irqsave(&tmr->lock, flags);
- if (tmr->running && (ppq != tmr->ppq)) {
- /* refuse to change ppq on running timers */
- /* because it will upset the song position (ticks) */
- spin_unlock_irqrestore(&tmr->lock, flags);
- snd_printd("seq: cannot change ppq of a running timer\n");
- return -EBUSY;
- }
-
- tmr->ppq = ppq;
- snd_seq_timer_set_tick_resolution(tmr);
- spin_unlock_irqrestore(&tmr->lock, flags);
- return 0;
-}
-
-/* set current tick position */
-int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr,
- snd_seq_tick_time_t position)
-{
- unsigned long flags;
-
- if (snd_BUG_ON(!tmr))
- return -EINVAL;
-
- spin_lock_irqsave(&tmr->lock, flags);
- tmr->tick.cur_tick = position;
- tmr->tick.fraction = 0;
- spin_unlock_irqrestore(&tmr->lock, flags);
- return 0;
-}
-
-/* set current real-time position */
-int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr,
- snd_seq_real_time_t position)
-{
- unsigned long flags;
-
- if (snd_BUG_ON(!tmr))
- return -EINVAL;
-
- snd_seq_sanity_real_time(&position);
- spin_lock_irqsave(&tmr->lock, flags);
- tmr->cur_time = position;
- spin_unlock_irqrestore(&tmr->lock, flags);
- return 0;
-}
-
-/* set timer skew */
-int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew,
- unsigned int base)
-{
- unsigned long flags;
-
- if (snd_BUG_ON(!tmr))
- return -EINVAL;
-
- /* FIXME */
- if (base != SKEW_BASE) {
- snd_printd("invalid skew base 0x%x\n", base);
- return -EINVAL;
- }
- spin_lock_irqsave(&tmr->lock, flags);
- tmr->skew = skew;
- spin_unlock_irqrestore(&tmr->lock, flags);
- return 0;
-}
-
-int snd_seq_timer_open(struct snd_seq_queue *q)
-{
- struct snd_timer_instance *t;
- struct snd_seq_timer *tmr;
- char str[32];
- int err;
-
- tmr = q->timer;
- if (snd_BUG_ON(!tmr))
- return -EINVAL;
- if (tmr->timeri)
- return -EBUSY;
- sprintf(str, "sequencer queue %i", q->queue);
- if (tmr->type != SNDRV_SEQ_TIMER_ALSA) /* standard ALSA timer */
- return -EINVAL;
- if (tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
- tmr->alsa_id.dev_sclass = SNDRV_TIMER_SCLASS_SEQUENCER;
- err = snd_timer_open(&t, str, &tmr->alsa_id, q->queue);
- if (err < 0 && tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_SLAVE) {
- if (tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_GLOBAL ||
- tmr->alsa_id.device != SNDRV_TIMER_GLOBAL_SYSTEM) {
- struct snd_timer_id tid;
- memset(&tid, 0, sizeof(tid));
- tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL;
- tid.dev_sclass = SNDRV_TIMER_SCLASS_SEQUENCER;
- tid.card = -1;
- tid.device = SNDRV_TIMER_GLOBAL_SYSTEM;
- err = snd_timer_open(&t, str, &tid, q->queue);
- }
- if (err < 0) {
- snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
- return err;
- }
- }
- t->callback = snd_seq_timer_interrupt;
- t->callback_data = q;
- t->flags |= SNDRV_TIMER_IFLG_AUTO;
- tmr->timeri = t;
- return 0;
-}
-
-int snd_seq_timer_close(struct snd_seq_queue *q)
-{
- struct snd_seq_timer *tmr;
-
- tmr = q->timer;
- if (snd_BUG_ON(!tmr))
- return -EINVAL;
- if (tmr->timeri) {
- snd_timer_stop(tmr->timeri);
- snd_timer_close(tmr->timeri);
- tmr->timeri = NULL;
- }
- return 0;
-}
-
-int snd_seq_timer_stop(struct snd_seq_timer * tmr)
-{
- if (! tmr->timeri)
- return -EINVAL;
- if (!tmr->running)
- return 0;
- tmr->running = 0;
- snd_timer_pause(tmr->timeri);
- return 0;
-}
-
-static int initialize_timer(struct snd_seq_timer *tmr)
-{
- struct snd_timer *t;
- unsigned long freq;
-
- t = tmr->timeri->timer;
- if (snd_BUG_ON(!t))
- return -EINVAL;
-
- freq = tmr->preferred_resolution;
- if (!freq)
- freq = DEFAULT_FREQUENCY;
- else if (freq < MIN_FREQUENCY)
- freq = MIN_FREQUENCY;
- else if (freq > MAX_FREQUENCY)
- freq = MAX_FREQUENCY;
-
- tmr->ticks = 1;
- if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {
- unsigned long r = t->hw.resolution;
- if (! r && t->hw.c_resolution)
- r = t->hw.c_resolution(t);
- if (r) {
- tmr->ticks = (unsigned int)(1000000000uL / (r * freq));
- if (! tmr->ticks)
- tmr->ticks = 1;
- }
- }
- tmr->initialized = 1;
- return 0;
-}
-
-int snd_seq_timer_start(struct snd_seq_timer * tmr)
-{
- if (! tmr->timeri)
- return -EINVAL;
- if (tmr->running)
- snd_seq_timer_stop(tmr);
- snd_seq_timer_reset(tmr);
- if (initialize_timer(tmr) < 0)
- return -EINVAL;
- snd_timer_start(tmr->timeri, tmr->ticks);
- tmr->running = 1;
- do_gettimeofday(&tmr->last_update);
- return 0;
-}
-
-int snd_seq_timer_continue(struct snd_seq_timer * tmr)
-{
- if (! tmr->timeri)
- return -EINVAL;
- if (tmr->running)
- return -EBUSY;
- if (! tmr->initialized) {
- snd_seq_timer_reset(tmr);
- if (initialize_timer(tmr) < 0)
- return -EINVAL;
- }
- snd_timer_start(tmr->timeri, tmr->ticks);
- tmr->running = 1;
- do_gettimeofday(&tmr->last_update);
- return 0;
-}
-
-/* return current 'real' time. use timeofday() to get better granularity. */
-snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
-{
- snd_seq_real_time_t cur_time;
-
- cur_time = tmr->cur_time;
- if (tmr->running) {
- struct timeval tm;
- int usec;
- do_gettimeofday(&tm);
- usec = (int)(tm.tv_usec - tmr->last_update.tv_usec);
- if (usec < 0) {
- cur_time.tv_nsec += (1000000 + usec) * 1000;
- cur_time.tv_sec += tm.tv_sec - tmr->last_update.tv_sec - 1;
- } else {
- cur_time.tv_nsec += usec * 1000;
- cur_time.tv_sec += tm.tv_sec - tmr->last_update.tv_sec;
- }
- snd_seq_sanity_real_time(&cur_time);
- }
-
- return cur_time;
-}
-
-/* TODO: use interpolation on tick queue (will only be useful for very
- high PPQ values) */
-snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr)
-{
- return tmr->tick.cur_tick;
-}
-
-
-#ifdef CONFIG_PROC_FS
-/* exported to seq_info.c */
-void snd_seq_info_timer_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- int idx;
- struct snd_seq_queue *q;
- struct snd_seq_timer *tmr;
- struct snd_timer_instance *ti;
- unsigned long resolution;
-
- for (idx = 0; idx < SNDRV_SEQ_MAX_QUEUES; idx++) {
- q = queueptr(idx);
- if (q == NULL)
- continue;
- if ((tmr = q->timer) == NULL ||
- (ti = tmr->timeri) == NULL) {
- queuefree(q);
- continue;
- }
- snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name);
- resolution = snd_timer_resolution(ti) * tmr->ticks;
- snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
- snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base);
- queuefree(q);
- }
-}
-#endif /* CONFIG_PROC_FS */
-
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_timer.h b/ANDROID_3.4.5/sound/core/seq/seq_timer.h
deleted file mode 100644
index 88dfb718..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_timer.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * ALSA sequencer Timer
- * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __SND_SEQ_TIMER_H
-#define __SND_SEQ_TIMER_H
-
-#include <sound/timer.h>
-#include <sound/seq_kernel.h>
-
-struct snd_seq_timer_tick {
- snd_seq_tick_time_t cur_tick; /* current tick */
- unsigned long resolution; /* time per tick in nsec */
- unsigned long fraction; /* current time per tick in nsec */
-};
-
-struct snd_seq_timer {
- /* ... tempo / offset / running state */
-
- unsigned int running:1, /* running state of queue */
- initialized:1; /* timer is initialized */
-
- unsigned int tempo; /* current tempo, us/tick */
- int ppq; /* time resolution, ticks/quarter */
-
- snd_seq_real_time_t cur_time; /* current time */
- struct snd_seq_timer_tick tick; /* current tick */
- int tick_updated;
-
- int type; /* timer type */
- struct snd_timer_id alsa_id; /* ALSA's timer ID */
- struct snd_timer_instance *timeri; /* timer instance */
- unsigned int ticks;
- unsigned long preferred_resolution; /* timer resolution, ticks/sec */
-
- unsigned int skew;
- unsigned int skew_base;
-
- struct timeval last_update; /* time of last clock update, used for interpolation */
-
- spinlock_t lock;
-};
-
-
-/* create new timer (constructor) */
-struct snd_seq_timer *snd_seq_timer_new(void);
-
-/* delete timer (destructor) */
-void snd_seq_timer_delete(struct snd_seq_timer **tmr);
-
-/* */
-static inline void snd_seq_timer_update_tick(struct snd_seq_timer_tick *tick,
- unsigned long resolution)
-{
- if (tick->resolution > 0) {
- tick->fraction += resolution;
- tick->cur_tick += (unsigned int)(tick->fraction / tick->resolution);
- tick->fraction %= tick->resolution;
- }
-}
-
-
-/* compare timestamp between events */
-/* return 1 if a >= b; otherwise return 0 */
-static inline int snd_seq_compare_tick_time(snd_seq_tick_time_t *a, snd_seq_tick_time_t *b)
-{
- /* compare ticks */
- return (*a >= *b);
-}
-
-static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, snd_seq_real_time_t *b)
-{
- /* compare real time */
- if (a->tv_sec > b->tv_sec)
- return 1;
- if ((a->tv_sec == b->tv_sec) && (a->tv_nsec >= b->tv_nsec))
- return 1;
- return 0;
-}
-
-
-static inline void snd_seq_sanity_real_time(snd_seq_real_time_t *tm)
-{
- while (tm->tv_nsec >= 1000000000) {
- /* roll-over */
- tm->tv_nsec -= 1000000000;
- tm->tv_sec++;
- }
-}
-
-
-/* increment timestamp */
-static inline void snd_seq_inc_real_time(snd_seq_real_time_t *tm, snd_seq_real_time_t *inc)
-{
- tm->tv_sec += inc->tv_sec;
- tm->tv_nsec += inc->tv_nsec;
- snd_seq_sanity_real_time(tm);
-}
-
-static inline void snd_seq_inc_time_nsec(snd_seq_real_time_t *tm, unsigned long nsec)
-{
- tm->tv_nsec += nsec;
- snd_seq_sanity_real_time(tm);
-}
-
-/* called by timer isr */
-struct snd_seq_queue;
-int snd_seq_timer_open(struct snd_seq_queue *q);
-int snd_seq_timer_close(struct snd_seq_queue *q);
-int snd_seq_timer_midi_open(struct snd_seq_queue *q);
-int snd_seq_timer_midi_close(struct snd_seq_queue *q);
-void snd_seq_timer_defaults(struct snd_seq_timer *tmr);
-void snd_seq_timer_reset(struct snd_seq_timer *tmr);
-int snd_seq_timer_stop(struct snd_seq_timer *tmr);
-int snd_seq_timer_start(struct snd_seq_timer *tmr);
-int snd_seq_timer_continue(struct snd_seq_timer *tmr);
-int snd_seq_timer_set_tempo(struct snd_seq_timer *tmr, int tempo);
-int snd_seq_timer_set_ppq(struct snd_seq_timer *tmr, int ppq);
-int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position);
-int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position);
-int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);
-snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr);
-snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr);
-
-extern int seq_default_timer_class;
-extern int seq_default_timer_sclass;
-extern int seq_default_timer_card;
-extern int seq_default_timer_device;
-extern int seq_default_timer_subdevice;
-extern int seq_default_timer_resolution;
-
-#endif
diff --git a/ANDROID_3.4.5/sound/core/seq/seq_virmidi.c b/ANDROID_3.4.5/sound/core/seq/seq_virmidi.c
deleted file mode 100644
index 4b50e604..00000000
--- a/ANDROID_3.4.5/sound/core/seq/seq_virmidi.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * Virtual Raw MIDI client on Sequencer
- *
- * Copyright (c) 2000 by Takashi Iwai <tiwai@suse.de>,
- * Jaroslav Kysela <perex@perex.cz>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/*
- * Virtual Raw MIDI client
- *
- * The virtual rawmidi client is a sequencer client which associate
- * a rawmidi device file. The created rawmidi device file can be
- * accessed as a normal raw midi, but its MIDI source and destination
- * are arbitrary. For example, a user-client software synth connected
- * to this port can be used as a normal midi device as well.
- *
- * The virtual rawmidi device accepts also multiple opens. Each file
- * has its own input buffer, so that no conflict would occur. The drain
- * of input/output buffer acts only to the local buffer.
- *
- */
-
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/rawmidi.h>
-#include <sound/info.h>
-#include <sound/control.h>
-#include <sound/minors.h>
-#include <sound/seq_kernel.h>
-#include <sound/seq_midi_event.h>
-#include <sound/seq_virmidi.h>
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("Virtual Raw MIDI client on Sequencer");
-MODULE_LICENSE("GPL");
-
-/*
- * initialize an event record
- */
-static void snd_virmidi_init_event(struct snd_virmidi *vmidi,
- struct snd_seq_event *ev)
-{
- memset(ev, 0, sizeof(*ev));
- ev->source.port = vmidi->port;
- switch (vmidi->seq_mode) {
- case SNDRV_VIRMIDI_SEQ_DISPATCH:
- ev->dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- break;
- case SNDRV_VIRMIDI_SEQ_ATTACH:
- /* FIXME: source and destination are same - not good.. */
- ev->dest.client = vmidi->client;
- ev->dest.port = vmidi->port;
- break;
- }
- ev->type = SNDRV_SEQ_EVENT_NONE;
-}
-
-/*
- * decode input event and put to read buffer of each opened file
- */
-static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
- struct snd_seq_event *ev)
-{
- struct snd_virmidi *vmidi;
- unsigned char msg[4];
- int len;
-
- read_lock(&rdev->filelist_lock);
- list_for_each_entry(vmidi, &rdev->filelist, list) {
- if (!vmidi->trigger)
- continue;
- if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
- if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
- continue;
- snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)snd_rawmidi_receive, vmidi->substream);
- } else {
- len = snd_midi_event_decode(vmidi->parser, msg, sizeof(msg), ev);
- if (len > 0)
- snd_rawmidi_receive(vmidi->substream, msg, len);
- }
- }
- read_unlock(&rdev->filelist_lock);
-
- return 0;
-}
-
-/*
- * receive an event from the remote virmidi port
- *
- * for rawmidi inputs, you can call this function from the event
- * handler of a remote port which is attached to the virmidi via
- * SNDRV_VIRMIDI_SEQ_ATTACH.
- */
-#if 0
-int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev)
-{
- struct snd_virmidi_dev *rdev;
-
- rdev = rmidi->private_data;
- return snd_virmidi_dev_receive_event(rdev, ev);
-}
-#endif /* 0 */
-
-/*
- * event handler of virmidi port
- */
-static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct,
- void *private_data, int atomic, int hop)
-{
- struct snd_virmidi_dev *rdev;
-
- rdev = private_data;
- if (!(rdev->flags & SNDRV_VIRMIDI_USE))
- return 0; /* ignored */
- return snd_virmidi_dev_receive_event(rdev, ev);
-}
-
-/*
- * trigger rawmidi stream for input
- */
-static void snd_virmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
-{
- struct snd_virmidi *vmidi = substream->runtime->private_data;
-
- if (up) {
- vmidi->trigger = 1;
- } else {
- vmidi->trigger = 0;
- }
-}
-
-/*
- * trigger rawmidi stream for output
- */
-static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
-{
- struct snd_virmidi *vmidi = substream->runtime->private_data;
- int count, res;
- unsigned char buf[32], *pbuf;
-
- if (up) {
- vmidi->trigger = 1;
- if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
- !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
- snd_rawmidi_transmit_ack(substream, substream->runtime->buffer_size - substream->runtime->avail);
- return; /* ignored */
- }
- if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
- if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
- return;
- vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
- }
- while (1) {
- count = snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
- if (count <= 0)
- break;
- pbuf = buf;
- while (count > 0) {
- res = snd_midi_event_encode(vmidi->parser, pbuf, count, &vmidi->event);
- if (res < 0) {
- snd_midi_event_reset_encode(vmidi->parser);
- continue;
- }
- snd_rawmidi_transmit_ack(substream, res);
- pbuf += res;
- count -= res;
- if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
- if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
- return;
- vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
- }
- }
- }
- } else {
- vmidi->trigger = 0;
- }
-}
-
-/*
- * open rawmidi handle for input
- */
-static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream)
-{
- struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
- struct snd_virmidi *vmidi;
- unsigned long flags;
-
- vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
- if (vmidi == NULL)
- return -ENOMEM;
- vmidi->substream = substream;
- if (snd_midi_event_new(0, &vmidi->parser) < 0) {
- kfree(vmidi);
- return -ENOMEM;
- }
- vmidi->seq_mode = rdev->seq_mode;
- vmidi->client = rdev->client;
- vmidi->port = rdev->port;
- runtime->private_data = vmidi;
- write_lock_irqsave(&rdev->filelist_lock, flags);
- list_add_tail(&vmidi->list, &rdev->filelist);
- write_unlock_irqrestore(&rdev->filelist_lock, flags);
- vmidi->rdev = rdev;
- return 0;
-}
-
-/*
- * open rawmidi handle for output
- */
-static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream)
-{
- struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
- struct snd_rawmidi_runtime *runtime = substream->runtime;
- struct snd_virmidi *vmidi;
-
- vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
- if (vmidi == NULL)
- return -ENOMEM;
- vmidi->substream = substream;
- if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &vmidi->parser) < 0) {
- kfree(vmidi);
- return -ENOMEM;
- }
- vmidi->seq_mode = rdev->seq_mode;
- vmidi->client = rdev->client;
- vmidi->port = rdev->port;
- snd_virmidi_init_event(vmidi, &vmidi->event);
- vmidi->rdev = rdev;
- runtime->private_data = vmidi;
- return 0;
-}
-
-/*
- * close rawmidi handle for input
- */
-static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
-{
- struct snd_virmidi *vmidi = substream->runtime->private_data;
- snd_midi_event_free(vmidi->parser);
- list_del(&vmidi->list);
- substream->runtime->private_data = NULL;
- kfree(vmidi);
- return 0;
-}
-
-/*
- * close rawmidi handle for output
- */
-static int snd_virmidi_output_close(struct snd_rawmidi_substream *substream)
-{
- struct snd_virmidi *vmidi = substream->runtime->private_data;
- snd_midi_event_free(vmidi->parser);
- substream->runtime->private_data = NULL;
- kfree(vmidi);
- return 0;
-}
-
-/*
- * subscribe callback - allow output to rawmidi device
- */
-static int snd_virmidi_subscribe(void *private_data,
- struct snd_seq_port_subscribe *info)
-{
- struct snd_virmidi_dev *rdev;
-
- rdev = private_data;
- if (!try_module_get(rdev->card->module))
- return -EFAULT;
- rdev->flags |= SNDRV_VIRMIDI_SUBSCRIBE;
- return 0;
-}
-
-/*
- * unsubscribe callback - disallow output to rawmidi device
- */
-static int snd_virmidi_unsubscribe(void *private_data,
- struct snd_seq_port_subscribe *info)
-{
- struct snd_virmidi_dev *rdev;
-
- rdev = private_data;
- rdev->flags &= ~SNDRV_VIRMIDI_SUBSCRIBE;
- module_put(rdev->card->module);
- return 0;
-}
-
-
-/*
- * use callback - allow input to rawmidi device
- */
-static int snd_virmidi_use(void *private_data,
- struct snd_seq_port_subscribe *info)
-{
- struct snd_virmidi_dev *rdev;
-
- rdev = private_data;
- if (!try_module_get(rdev->card->module))
- return -EFAULT;
- rdev->flags |= SNDRV_VIRMIDI_USE;
- return 0;
-}
-
-/*
- * unuse callback - disallow input to rawmidi device
- */
-static int snd_virmidi_unuse(void *private_data,
- struct snd_seq_port_subscribe *info)
-{
- struct snd_virmidi_dev *rdev;
-
- rdev = private_data;
- rdev->flags &= ~SNDRV_VIRMIDI_USE;
- module_put(rdev->card->module);
- return 0;
-}
-
-
-/*
- * Register functions
- */
-
-static struct snd_rawmidi_ops snd_virmidi_input_ops = {
- .open = snd_virmidi_input_open,
- .close = snd_virmidi_input_close,
- .trigger = snd_virmidi_input_trigger,
-};
-
-static struct snd_rawmidi_ops snd_virmidi_output_ops = {
- .open = snd_virmidi_output_open,
- .close = snd_virmidi_output_close,
- .trigger = snd_virmidi_output_trigger,
-};
-
-/*
- * create a sequencer client and a port
- */
-static int snd_virmidi_dev_attach_seq(struct snd_virmidi_dev *rdev)
-{
- int client;
- struct snd_seq_port_callback pcallbacks;
- struct snd_seq_port_info *pinfo;
- int err;
-
- if (rdev->client >= 0)
- return 0;
-
- pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
- if (!pinfo) {
- err = -ENOMEM;
- goto __error;
- }
-
- client = snd_seq_create_kernel_client(rdev->card, rdev->device,
- "%s %d-%d", rdev->rmidi->name,
- rdev->card->number,
- rdev->device);
- if (client < 0) {
- err = client;
- goto __error;
- }
- rdev->client = client;
-
- /* create a port */
- pinfo->addr.client = client;
- sprintf(pinfo->name, "VirMIDI %d-%d", rdev->card->number, rdev->device);
- /* set all capabilities */
- pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
- pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
- pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
- pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
- | SNDRV_SEQ_PORT_TYPE_SOFTWARE
- | SNDRV_SEQ_PORT_TYPE_PORT;
- pinfo->midi_channels = 16;
- memset(&pcallbacks, 0, sizeof(pcallbacks));
- pcallbacks.owner = THIS_MODULE;
- pcallbacks.private_data = rdev;
- pcallbacks.subscribe = snd_virmidi_subscribe;
- pcallbacks.unsubscribe = snd_virmidi_unsubscribe;
- pcallbacks.use = snd_virmidi_use;
- pcallbacks.unuse = snd_virmidi_unuse;
- pcallbacks.event_input = snd_virmidi_event_input;
- pinfo->kernel = &pcallbacks;
- err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo);
- if (err < 0) {
- snd_seq_delete_kernel_client(client);
- rdev->client = -1;
- goto __error;
- }
-
- rdev->port = pinfo->addr.port;
- err = 0; /* success */
-
- __error:
- kfree(pinfo);
- return err;
-}
-
-
-/*
- * release the sequencer client
- */
-static void snd_virmidi_dev_detach_seq(struct snd_virmidi_dev *rdev)
-{
- if (rdev->client >= 0) {
- snd_seq_delete_kernel_client(rdev->client);
- rdev->client = -1;
- }
-}
-
-/*
- * register the device
- */
-static int snd_virmidi_dev_register(struct snd_rawmidi *rmidi)
-{
- struct snd_virmidi_dev *rdev = rmidi->private_data;
- int err;
-
- switch (rdev->seq_mode) {
- case SNDRV_VIRMIDI_SEQ_DISPATCH:
- err = snd_virmidi_dev_attach_seq(rdev);
- if (err < 0)
- return err;
- break;
- case SNDRV_VIRMIDI_SEQ_ATTACH:
- if (rdev->client == 0)
- return -EINVAL;
- /* should check presence of port more strictly.. */
- break;
- default:
- snd_printk(KERN_ERR "seq_mode is not set: %d\n", rdev->seq_mode);
- return -EINVAL;
- }
- return 0;
-}
-
-
-/*
- * unregister the device
- */
-static int snd_virmidi_dev_unregister(struct snd_rawmidi *rmidi)
-{
- struct snd_virmidi_dev *rdev = rmidi->private_data;
-
- if (rdev->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH)
- snd_virmidi_dev_detach_seq(rdev);
- return 0;
-}
-
-/*
- *
- */
-static struct snd_rawmidi_global_ops snd_virmidi_global_ops = {
- .dev_register = snd_virmidi_dev_register,
- .dev_unregister = snd_virmidi_dev_unregister,
-};
-
-/*
- * free device
- */
-static void snd_virmidi_free(struct snd_rawmidi *rmidi)
-{
- struct snd_virmidi_dev *rdev = rmidi->private_data;
- kfree(rdev);
-}
-
-/*
- * create a new device
- *
- */
-/* exported */
-int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmidi)
-{
- struct snd_rawmidi *rmidi;
- struct snd_virmidi_dev *rdev;
- int err;
-
- *rrmidi = NULL;
- if ((err = snd_rawmidi_new(card, "VirMidi", device,
- 16, /* may be configurable */
- 16, /* may be configurable */
- &rmidi)) < 0)
- return err;
- strcpy(rmidi->name, rmidi->id);
- rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
- if (rdev == NULL) {
- snd_device_free(card, rmidi);
- return -ENOMEM;
- }
- rdev->card = card;
- rdev->rmidi = rmidi;
- rdev->device = device;
- rdev->client = -1;
- rwlock_init(&rdev->filelist_lock);
- INIT_LIST_HEAD(&rdev->filelist);
- rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH;
- rmidi->private_data = rdev;
- rmidi->private_free = snd_virmidi_free;
- rmidi->ops = &snd_virmidi_global_ops;
- snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_virmidi_input_ops);
- snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_virmidi_output_ops);
- rmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT |
- SNDRV_RAWMIDI_INFO_OUTPUT |
- SNDRV_RAWMIDI_INFO_DUPLEX;
- *rrmidi = rmidi;
- return 0;
-}
-
-/*
- * ENTRY functions
- */
-
-static int __init alsa_virmidi_init(void)
-{
- return 0;
-}
-
-static void __exit alsa_virmidi_exit(void)
-{
-}
-
-module_init(alsa_virmidi_init)
-module_exit(alsa_virmidi_exit)
-
-EXPORT_SYMBOL(snd_virmidi_new);
diff --git a/ANDROID_3.4.5/sound/core/sgbuf.c b/ANDROID_3.4.5/sound/core/sgbuf.c
deleted file mode 100644
index 4e7ec2b4..00000000
--- a/ANDROID_3.4.5/sound/core/sgbuf.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Scatter-Gather buffer
- *
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <sound/memalloc.h>
-
-
-/* table entries are align to 32 */
-#define SGBUF_TBL_ALIGN 32
-#define sgbuf_align_table(tbl) ALIGN((tbl), SGBUF_TBL_ALIGN)
-
-int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
-{
- struct snd_sg_buf *sgbuf = dmab->private_data;
- struct snd_dma_buffer tmpb;
- int i;
-
- if (! sgbuf)
- return -EINVAL;
-
- if (dmab->area)
- vunmap(dmab->area);
- dmab->area = NULL;
-
- tmpb.dev.type = SNDRV_DMA_TYPE_DEV;
- tmpb.dev.dev = sgbuf->dev;
- for (i = 0; i < sgbuf->pages; i++) {
- if (!(sgbuf->table[i].addr & ~PAGE_MASK))
- continue; /* continuous pages */
- tmpb.area = sgbuf->table[i].buf;
- tmpb.addr = sgbuf->table[i].addr & PAGE_MASK;
- tmpb.bytes = (sgbuf->table[i].addr & ~PAGE_MASK) << PAGE_SHIFT;
- snd_dma_free_pages(&tmpb);
- }
-
- kfree(sgbuf->table);
- kfree(sgbuf->page_table);
- kfree(sgbuf);
- dmab->private_data = NULL;
-
- return 0;
-}
-
-#define MAX_ALLOC_PAGES 32
-
-void *snd_malloc_sgbuf_pages(struct device *device,
- size_t size, struct snd_dma_buffer *dmab,
- size_t *res_size)
-{
- struct snd_sg_buf *sgbuf;
- unsigned int i, pages, chunk, maxpages;
- struct snd_dma_buffer tmpb;
- struct snd_sg_page *table;
- struct page **pgtable;
-
- dmab->area = NULL;
- dmab->addr = 0;
- dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
- if (! sgbuf)
- return NULL;
- sgbuf->dev = device;
- pages = snd_sgbuf_aligned_pages(size);
- sgbuf->tblsize = sgbuf_align_table(pages);
- table = kcalloc(sgbuf->tblsize, sizeof(*table), GFP_KERNEL);
- if (!table)
- goto _failed;
- sgbuf->table = table;
- pgtable = kcalloc(sgbuf->tblsize, sizeof(*pgtable), GFP_KERNEL);
- if (!pgtable)
- goto _failed;
- sgbuf->page_table = pgtable;
-
- /* allocate pages */
- maxpages = MAX_ALLOC_PAGES;
- while (pages > 0) {
- chunk = pages;
- /* don't be too eager to take a huge chunk */
- if (chunk > maxpages)
- chunk = maxpages;
- chunk <<= PAGE_SHIFT;
- if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, device,
- chunk, &tmpb) < 0) {
- if (!sgbuf->pages)
- return NULL;
- if (!res_size)
- goto _failed;
- size = sgbuf->pages * PAGE_SIZE;
- break;
- }
- chunk = tmpb.bytes >> PAGE_SHIFT;
- for (i = 0; i < chunk; i++) {
- table->buf = tmpb.area;
- table->addr = tmpb.addr;
- if (!i)
- table->addr |= chunk; /* mark head */
- table++;
- *pgtable++ = virt_to_page(tmpb.area);
- tmpb.area += PAGE_SIZE;
- tmpb.addr += PAGE_SIZE;
- }
- sgbuf->pages += chunk;
- pages -= chunk;
- if (chunk < maxpages)
- maxpages = chunk;
- }
-
- sgbuf->size = size;
- dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, PAGE_KERNEL);
- if (! dmab->area)
- goto _failed;
- if (res_size)
- *res_size = sgbuf->size;
- return dmab->area;
-
- _failed:
- snd_free_sgbuf_pages(dmab); /* free the table */
- return NULL;
-}
diff --git a/ANDROID_3.4.5/sound/core/sound.c b/ANDROID_3.4.5/sound/core/sound.c
deleted file mode 100644
index 3700d96f..00000000
--- a/ANDROID_3.4.5/sound/core/sound.c
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Advanced Linux Sound Architecture
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <sound/info.h>
-#include <sound/version.h>
-#include <sound/control.h>
-#include <sound/initval.h>
-#include <linux/kmod.h>
-#include <linux/mutex.h>
-
-static int major = CONFIG_SND_MAJOR;
-int snd_major;
-EXPORT_SYMBOL(snd_major);
-
-static int cards_limit = 1;
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards.");
-MODULE_LICENSE("GPL");
-module_param(major, int, 0444);
-MODULE_PARM_DESC(major, "Major # for sound driver.");
-module_param(cards_limit, int, 0444);
-MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards.");
-MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
-
-/* this one holds the actual max. card number currently available.
- * as default, it's identical with cards_limit option. when more
- * modules are loaded manually, this limit number increases, too.
- */
-int snd_ecards_limit;
-EXPORT_SYMBOL(snd_ecards_limit);
-
-static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
-static DEFINE_MUTEX(sound_mutex);
-
-#ifdef CONFIG_MODULES
-
-/**
- * snd_request_card - try to load the card module
- * @card: the card number
- *
- * Tries to load the module "snd-card-X" for the given card number
- * via request_module. Returns immediately if already loaded.
- */
-void snd_request_card(int card)
-{
- if (snd_card_locked(card))
- return;
- if (card < 0 || card >= cards_limit)
- return;
- request_module("snd-card-%i", card);
-}
-
-EXPORT_SYMBOL(snd_request_card);
-
-static void snd_request_other(int minor)
-{
- char *str;
-
- switch (minor) {
- case SNDRV_MINOR_SEQUENCER: str = "snd-seq"; break;
- case SNDRV_MINOR_TIMER: str = "snd-timer"; break;
- default: return;
- }
- request_module(str);
-}
-
-#endif /* modular kernel */
-
-/**
- * snd_lookup_minor_data - get user data of a registered device
- * @minor: the minor number
- * @type: device type (SNDRV_DEVICE_TYPE_XXX)
- *
- * Checks that a minor device with the specified type is registered, and returns
- * its user data pointer.
- *
- * This function increments the reference counter of the card instance
- * if an associated instance with the given minor number and type is found.
- * The caller must call snd_card_unref() appropriately later.
- */
-void *snd_lookup_minor_data(unsigned int minor, int type)
-{
- struct snd_minor *mreg;
- void *private_data;
-
- if (minor >= ARRAY_SIZE(snd_minors))
- return NULL;
- mutex_lock(&sound_mutex);
- mreg = snd_minors[minor];
- if (mreg && mreg->type == type) {
- private_data = mreg->private_data;
- if (private_data && mreg->card_ptr)
- atomic_inc(&mreg->card_ptr->refcount);
- } else
- private_data = NULL;
- mutex_unlock(&sound_mutex);
- return private_data;
-}
-
-EXPORT_SYMBOL(snd_lookup_minor_data);
-
-#ifdef CONFIG_MODULES
-static struct snd_minor *autoload_device(unsigned int minor)
-{
- int dev;
- mutex_unlock(&sound_mutex); /* release lock temporarily */
- dev = SNDRV_MINOR_DEVICE(minor);
- if (dev == SNDRV_MINOR_CONTROL) {
- /* /dev/aloadC? */
- int card = SNDRV_MINOR_CARD(minor);
- if (snd_cards[card] == NULL)
- snd_request_card(card);
- } else if (dev == SNDRV_MINOR_GLOBAL) {
- /* /dev/aloadSEQ */
- snd_request_other(minor);
- }
- mutex_lock(&sound_mutex); /* reacuire lock */
- return snd_minors[minor];
-}
-#else /* !CONFIG_MODULES */
-#define autoload_device(minor) NULL
-#endif /* CONFIG_MODULES */
-
-static int snd_open(struct inode *inode, struct file *file)
-{
- unsigned int minor = iminor(inode);
- struct snd_minor *mptr = NULL;
- const struct file_operations *old_fops;
- int err = 0;
-
- if (minor >= ARRAY_SIZE(snd_minors))
- return -ENODEV;
- mutex_lock(&sound_mutex);
- mptr = snd_minors[minor];
- if (mptr == NULL) {
- mptr = autoload_device(minor);
- if (!mptr) {
- mutex_unlock(&sound_mutex);
- return -ENODEV;
- }
- }
- old_fops = file->f_op;
- file->f_op = fops_get(mptr->f_ops);
- if (file->f_op == NULL) {
- file->f_op = old_fops;
- err = -ENODEV;
- }
- mutex_unlock(&sound_mutex);
- if (err < 0)
- return err;
-
- if (file->f_op->open) {
- err = file->f_op->open(inode, file);
- if (err) {
- fops_put(file->f_op);
- file->f_op = fops_get(old_fops);
- }
- }
- fops_put(old_fops);
- return err;
-}
-
-static const struct file_operations snd_fops =
-{
- .owner = THIS_MODULE,
- .open = snd_open,
- .llseek = noop_llseek,
-};
-
-#ifdef CONFIG_SND_DYNAMIC_MINORS
-static int snd_find_free_minor(int type)
-{
- int minor;
-
- /* static minors for module auto loading */
- if (type == SNDRV_DEVICE_TYPE_SEQUENCER)
- return SNDRV_MINOR_SEQUENCER;
- if (type == SNDRV_DEVICE_TYPE_TIMER)
- return SNDRV_MINOR_TIMER;
-
- for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) {
- /* skip static minors still used for module auto loading */
- if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL)
- continue;
- if (minor == SNDRV_MINOR_SEQUENCER ||
- minor == SNDRV_MINOR_TIMER)
- continue;
- if (!snd_minors[minor])
- return minor;
- }
- return -EBUSY;
-}
-#else
-static int snd_kernel_minor(int type, struct snd_card *card, int dev)
-{
- int minor;
-
- switch (type) {
- case SNDRV_DEVICE_TYPE_SEQUENCER:
- case SNDRV_DEVICE_TYPE_TIMER:
- minor = type;
- break;
- case SNDRV_DEVICE_TYPE_CONTROL:
- if (snd_BUG_ON(!card))
- return -EINVAL;
- minor = SNDRV_MINOR(card->number, type);
- break;
- case SNDRV_DEVICE_TYPE_HWDEP:
- case SNDRV_DEVICE_TYPE_RAWMIDI:
- case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
- case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
- case SNDRV_DEVICE_TYPE_COMPRESS:
- if (snd_BUG_ON(!card))
- return -EINVAL;
- minor = SNDRV_MINOR(card->number, type + dev);
- break;
- default:
- return -EINVAL;
- }
- if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OS_MINORS))
- return -EINVAL;
- return minor;
-}
-#endif
-
-/**
- * snd_register_device_for_dev - Register the ALSA device file for the card
- * @type: the device type, SNDRV_DEVICE_TYPE_XXX
- * @card: the card instance
- * @dev: the device index
- * @f_ops: the file operations
- * @private_data: user pointer for f_ops->open()
- * @name: the device file name
- * @device: the &struct device to link this new device to
- *
- * Registers an ALSA device file for the given card.
- * The operators have to be set in reg parameter.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
- const struct file_operations *f_ops,
- void *private_data,
- const char *name, struct device *device)
-{
- int minor;
- struct snd_minor *preg;
-
- if (snd_BUG_ON(!name))
- return -EINVAL;
- preg = kmalloc(sizeof *preg, GFP_KERNEL);
- if (preg == NULL)
- return -ENOMEM;
- preg->type = type;
- preg->card = card ? card->number : -1;
- preg->device = dev;
- preg->f_ops = f_ops;
- preg->private_data = private_data;
- preg->card_ptr = card;
- mutex_lock(&sound_mutex);
-#ifdef CONFIG_SND_DYNAMIC_MINORS
- minor = snd_find_free_minor(type);
-#else
- minor = snd_kernel_minor(type, card, dev);
- if (minor >= 0 && snd_minors[minor])
- minor = -EBUSY;
-#endif
- if (minor < 0) {
- mutex_unlock(&sound_mutex);
- kfree(preg);
- return minor;
- }
- snd_minors[minor] = preg;
- preg->dev = device_create(sound_class, device, MKDEV(major, minor),
- private_data, "%s", name);
- if (IS_ERR(preg->dev)) {
- snd_minors[minor] = NULL;
- mutex_unlock(&sound_mutex);
- minor = PTR_ERR(preg->dev);
- kfree(preg);
- return minor;
- }
-
- mutex_unlock(&sound_mutex);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_register_device_for_dev);
-
-/* find the matching minor record
- * return the index of snd_minor, or -1 if not found
- */
-static int find_snd_minor(int type, struct snd_card *card, int dev)
-{
- int cardnum, minor;
- struct snd_minor *mptr;
-
- cardnum = card ? card->number : -1;
- for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor)
- if ((mptr = snd_minors[minor]) != NULL &&
- mptr->type == type &&
- mptr->card == cardnum &&
- mptr->device == dev)
- return minor;
- return -1;
-}
-
-/**
- * snd_unregister_device - unregister the device on the given card
- * @type: the device type, SNDRV_DEVICE_TYPE_XXX
- * @card: the card instance
- * @dev: the device index
- *
- * Unregisters the device file already registered via
- * snd_register_device().
- *
- * Returns zero if sucecessful, or a negative error code on failure
- */
-int snd_unregister_device(int type, struct snd_card *card, int dev)
-{
- int minor;
-
- mutex_lock(&sound_mutex);
- minor = find_snd_minor(type, card, dev);
- if (minor < 0) {
- mutex_unlock(&sound_mutex);
- return -EINVAL;
- }
-
- device_destroy(sound_class, MKDEV(major, minor));
-
- kfree(snd_minors[minor]);
- snd_minors[minor] = NULL;
- mutex_unlock(&sound_mutex);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_unregister_device);
-
-int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
- struct device_attribute *attr)
-{
- int minor, ret = -EINVAL;
- struct device *d;
-
- mutex_lock(&sound_mutex);
- minor = find_snd_minor(type, card, dev);
- if (minor >= 0 && (d = snd_minors[minor]->dev) != NULL)
- ret = device_create_file(d, attr);
- mutex_unlock(&sound_mutex);
- return ret;
-
-}
-
-EXPORT_SYMBOL(snd_add_device_sysfs_file);
-
-#ifdef CONFIG_PROC_FS
-/*
- * INFO PART
- */
-
-static struct snd_info_entry *snd_minor_info_entry;
-
-static const char *snd_device_type_name(int type)
-{
- switch (type) {
- case SNDRV_DEVICE_TYPE_CONTROL:
- return "control";
- case SNDRV_DEVICE_TYPE_HWDEP:
- return "hardware dependent";
- case SNDRV_DEVICE_TYPE_RAWMIDI:
- return "raw midi";
- case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
- return "digital audio playback";
- case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
- return "digital audio capture";
- case SNDRV_DEVICE_TYPE_SEQUENCER:
- return "sequencer";
- case SNDRV_DEVICE_TYPE_TIMER:
- return "timer";
- default:
- return "?";
- }
-}
-
-static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
-{
- int minor;
- struct snd_minor *mptr;
-
- mutex_lock(&sound_mutex);
- for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) {
- if (!(mptr = snd_minors[minor]))
- continue;
- if (mptr->card >= 0) {
- if (mptr->device >= 0)
- snd_iprintf(buffer, "%3i: [%2i-%2i]: %s\n",
- minor, mptr->card, mptr->device,
- snd_device_type_name(mptr->type));
- else
- snd_iprintf(buffer, "%3i: [%2i] : %s\n",
- minor, mptr->card,
- snd_device_type_name(mptr->type));
- } else
- snd_iprintf(buffer, "%3i: : %s\n", minor,
- snd_device_type_name(mptr->type));
- }
- mutex_unlock(&sound_mutex);
-}
-
-int __init snd_minor_info_init(void)
-{
- struct snd_info_entry *entry;
-
- entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL);
- if (entry) {
- entry->c.text.read = snd_minor_info_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- snd_minor_info_entry = entry;
- return 0;
-}
-
-int __exit snd_minor_info_done(void)
-{
- snd_info_free_entry(snd_minor_info_entry);
- return 0;
-}
-#endif /* CONFIG_PROC_FS */
-
-/*
- * INIT PART
- */
-
-static int __init alsa_sound_init(void)
-{
- snd_major = major;
- snd_ecards_limit = cards_limit;
- if (register_chrdev(major, "alsa", &snd_fops)) {
- snd_printk(KERN_ERR "unable to register native major device number %d\n", major);
- return -EIO;
- }
- if (snd_info_init() < 0) {
- unregister_chrdev(major, "alsa");
- return -ENOMEM;
- }
- snd_info_minor_register();
-#ifndef MODULE
- printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
-#endif
- return 0;
-}
-
-static void __exit alsa_sound_exit(void)
-{
- snd_info_minor_unregister();
- snd_info_done();
- unregister_chrdev(major, "alsa");
-}
-
-subsys_initcall(alsa_sound_init);
-module_exit(alsa_sound_exit);
diff --git a/ANDROID_3.4.5/sound/core/sound_oss.c b/ANDROID_3.4.5/sound/core/sound_oss.c
deleted file mode 100644
index ec860091..00000000
--- a/ANDROID_3.4.5/sound/core/sound_oss.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Advanced Linux Sound Architecture
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifdef CONFIG_SND_OSSEMUL
-
-#if !defined(CONFIG_SOUND) && !(defined(MODULE) && defined(CONFIG_SOUND_MODULE))
-#error "Enable the OSS soundcore multiplexer (CONFIG_SOUND) in the kernel."
-#endif
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <sound/core.h>
-#include <sound/minors.h>
-#include <sound/info.h>
-#include <linux/sound.h>
-#include <linux/mutex.h>
-
-#define SNDRV_OSS_MINORS 128
-
-static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
-static DEFINE_MUTEX(sound_oss_mutex);
-
-/* NOTE: This function increments the refcount of the associated card like
- * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately
- */
-void *snd_lookup_oss_minor_data(unsigned int minor, int type)
-{
- struct snd_minor *mreg;
- void *private_data;
-
- if (minor >= ARRAY_SIZE(snd_oss_minors))
- return NULL;
- mutex_lock(&sound_oss_mutex);
- mreg = snd_oss_minors[minor];
- if (mreg && mreg->type == type) {
- private_data = mreg->private_data;
- if (private_data && mreg->card_ptr)
- atomic_inc(&mreg->card_ptr->refcount);
- } else
- private_data = NULL;
- mutex_unlock(&sound_oss_mutex);
- return private_data;
-}
-
-EXPORT_SYMBOL(snd_lookup_oss_minor_data);
-
-static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
-{
- int minor;
-
- switch (type) {
- case SNDRV_OSS_DEVICE_TYPE_MIXER:
- if (snd_BUG_ON(!card || dev < 0 || dev > 1))
- return -EINVAL;
- minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIXER1 : SNDRV_MINOR_OSS_MIXER));
- break;
- case SNDRV_OSS_DEVICE_TYPE_SEQUENCER:
- minor = SNDRV_MINOR_OSS_SEQUENCER;
- break;
- case SNDRV_OSS_DEVICE_TYPE_MUSIC:
- minor = SNDRV_MINOR_OSS_MUSIC;
- break;
- case SNDRV_OSS_DEVICE_TYPE_PCM:
- if (snd_BUG_ON(!card || dev < 0 || dev > 1))
- return -EINVAL;
- minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_PCM1 : SNDRV_MINOR_OSS_PCM));
- break;
- case SNDRV_OSS_DEVICE_TYPE_MIDI:
- if (snd_BUG_ON(!card || dev < 0 || dev > 1))
- return -EINVAL;
- minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIDI1 : SNDRV_MINOR_OSS_MIDI));
- break;
- case SNDRV_OSS_DEVICE_TYPE_DMFM:
- minor = SNDRV_MINOR_OSS(card->number, SNDRV_MINOR_OSS_DMFM);
- break;
- case SNDRV_OSS_DEVICE_TYPE_SNDSTAT:
- minor = SNDRV_MINOR_OSS_SNDSTAT;
- break;
- default:
- return -EINVAL;
- }
- if (minor < 0 || minor >= SNDRV_OSS_MINORS)
- return -EINVAL;
- return minor;
-}
-
-int snd_register_oss_device(int type, struct snd_card *card, int dev,
- const struct file_operations *f_ops, void *private_data,
- const char *name)
-{
- int minor = snd_oss_kernel_minor(type, card, dev);
- int minor_unit;
- struct snd_minor *preg;
- int cidx = SNDRV_MINOR_OSS_CARD(minor);
- int track2 = -1;
- int register1 = -1, register2 = -1;
- struct device *carddev = snd_card_get_device_link(card);
-
- if (card && card->number >= 8)
- return 0; /* ignore silently */
- if (minor < 0)
- return minor;
- preg = kmalloc(sizeof(struct snd_minor), GFP_KERNEL);
- if (preg == NULL)
- return -ENOMEM;
- preg->type = type;
- preg->card = card ? card->number : -1;
- preg->device = dev;
- preg->f_ops = f_ops;
- preg->private_data = private_data;
- preg->card_ptr = card;
- mutex_lock(&sound_oss_mutex);
- snd_oss_minors[minor] = preg;
- minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
- switch (minor_unit) {
- case SNDRV_MINOR_OSS_PCM:
- track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO);
- break;
- case SNDRV_MINOR_OSS_MIDI:
- track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI);
- break;
- case SNDRV_MINOR_OSS_MIDI1:
- track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
- break;
- }
- register1 = register_sound_special_device(f_ops, minor, carddev);
- if (register1 != minor)
- goto __end;
- if (track2 >= 0) {
- register2 = register_sound_special_device(f_ops, track2,
- carddev);
- if (register2 != track2)
- goto __end;
- snd_oss_minors[track2] = preg;
- }
- mutex_unlock(&sound_oss_mutex);
- return 0;
-
- __end:
- if (register2 >= 0)
- unregister_sound_special(register2);
- if (register1 >= 0)
- unregister_sound_special(register1);
- snd_oss_minors[minor] = NULL;
- mutex_unlock(&sound_oss_mutex);
- kfree(preg);
- return -EBUSY;
-}
-
-EXPORT_SYMBOL(snd_register_oss_device);
-
-int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
-{
- int minor = snd_oss_kernel_minor(type, card, dev);
- int cidx = SNDRV_MINOR_OSS_CARD(minor);
- int track2 = -1;
- struct snd_minor *mptr;
-
- if (card && card->number >= 8)
- return 0;
- if (minor < 0)
- return minor;
- mutex_lock(&sound_oss_mutex);
- mptr = snd_oss_minors[minor];
- if (mptr == NULL) {
- mutex_unlock(&sound_oss_mutex);
- return -ENOENT;
- }
- unregister_sound_special(minor);
- switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
- case SNDRV_MINOR_OSS_PCM:
- track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO);
- break;
- case SNDRV_MINOR_OSS_MIDI:
- track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI);
- break;
- case SNDRV_MINOR_OSS_MIDI1:
- track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
- break;
- }
- if (track2 >= 0) {
- unregister_sound_special(track2);
- snd_oss_minors[track2] = NULL;
- }
- snd_oss_minors[minor] = NULL;
- mutex_unlock(&sound_oss_mutex);
- kfree(mptr);
- return 0;
-}
-
-EXPORT_SYMBOL(snd_unregister_oss_device);
-
-/*
- * INFO PART
- */
-
-#ifdef CONFIG_PROC_FS
-
-static struct snd_info_entry *snd_minor_info_oss_entry;
-
-static const char *snd_oss_device_type_name(int type)
-{
- switch (type) {
- case SNDRV_OSS_DEVICE_TYPE_MIXER:
- return "mixer";
- case SNDRV_OSS_DEVICE_TYPE_SEQUENCER:
- case SNDRV_OSS_DEVICE_TYPE_MUSIC:
- return "sequencer";
- case SNDRV_OSS_DEVICE_TYPE_PCM:
- return "digital audio";
- case SNDRV_OSS_DEVICE_TYPE_MIDI:
- return "raw midi";
- case SNDRV_OSS_DEVICE_TYPE_DMFM:
- return "hardware dependent";
- default:
- return "?";
- }
-}
-
-static void snd_minor_info_oss_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- int minor;
- struct snd_minor *mptr;
-
- mutex_lock(&sound_oss_mutex);
- for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) {
- if (!(mptr = snd_oss_minors[minor]))
- continue;
- if (mptr->card >= 0)
- snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor,
- mptr->card, mptr->device,
- snd_oss_device_type_name(mptr->type));
- else
- snd_iprintf(buffer, "%3i: : %s\n", minor,
- snd_oss_device_type_name(mptr->type));
- }
- mutex_unlock(&sound_oss_mutex);
-}
-
-
-int __init snd_minor_info_oss_init(void)
-{
- struct snd_info_entry *entry;
-
- entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root);
- if (entry) {
- entry->c.text.read = snd_minor_info_oss_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- snd_minor_info_oss_entry = entry;
- return 0;
-}
-
-int __exit snd_minor_info_oss_done(void)
-{
- snd_info_free_entry(snd_minor_info_oss_entry);
- return 0;
-}
-#endif /* CONFIG_PROC_FS */
-
-#endif /* CONFIG_SND_OSSEMUL */
diff --git a/ANDROID_3.4.5/sound/core/timer.c b/ANDROID_3.4.5/sound/core/timer.c
deleted file mode 100644
index 6ddcf06f..00000000
--- a/ANDROID_3.4.5/sound/core/timer.c
+++ /dev/null
@@ -1,1999 +0,0 @@
-/*
- * Timers abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <sound/core.h>
-#include <sound/timer.h>
-#include <sound/control.h>
-#include <sound/info.h>
-#include <sound/minors.h>
-#include <sound/initval.h>
-#include <linux/kmod.h>
-
-#if defined(CONFIG_SND_HRTIMER) || defined(CONFIG_SND_HRTIMER_MODULE)
-#define DEFAULT_TIMER_LIMIT 4
-#elif defined(CONFIG_SND_RTCTIMER) || defined(CONFIG_SND_RTCTIMER_MODULE)
-#define DEFAULT_TIMER_LIMIT 2
-#else
-#define DEFAULT_TIMER_LIMIT 1
-#endif
-
-static int timer_limit = DEFAULT_TIMER_LIMIT;
-static int timer_tstamp_monotonic = 1;
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("ALSA timer interface");
-MODULE_LICENSE("GPL");
-module_param(timer_limit, int, 0444);
-MODULE_PARM_DESC(timer_limit, "Maximum global timers in system.");
-module_param(timer_tstamp_monotonic, int, 0444);
-MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for timestamps (default).");
-
-MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_TIMER);
-MODULE_ALIAS("devname:snd/timer");
-
-struct snd_timer_user {
- struct snd_timer_instance *timeri;
- int tread; /* enhanced read with timestamps and events */
- unsigned long ticks;
- unsigned long overrun;
- int qhead;
- int qtail;
- int qused;
- int queue_size;
- struct snd_timer_read *queue;
- struct snd_timer_tread *tqueue;
- spinlock_t qlock;
- unsigned long last_resolution;
- unsigned int filter;
- struct timespec tstamp; /* trigger tstamp */
- wait_queue_head_t qchange_sleep;
- struct fasync_struct *fasync;
- struct mutex tread_sem;
-};
-
-/* list of timers */
-static LIST_HEAD(snd_timer_list);
-
-/* list of slave instances */
-static LIST_HEAD(snd_timer_slave_list);
-
-/* lock for slave active lists */
-static DEFINE_SPINLOCK(slave_active_lock);
-
-static DEFINE_MUTEX(register_mutex);
-
-static int snd_timer_free(struct snd_timer *timer);
-static int snd_timer_dev_free(struct snd_device *device);
-static int snd_timer_dev_register(struct snd_device *device);
-static int snd_timer_dev_disconnect(struct snd_device *device);
-
-static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left);
-
-/*
- * create a timer instance with the given owner string.
- * when timer is not NULL, increments the module counter
- */
-static struct snd_timer_instance *snd_timer_instance_new(char *owner,
- struct snd_timer *timer)
-{
- struct snd_timer_instance *timeri;
- timeri = kzalloc(sizeof(*timeri), GFP_KERNEL);
- if (timeri == NULL)
- return NULL;
- timeri->owner = kstrdup(owner, GFP_KERNEL);
- if (! timeri->owner) {
- kfree(timeri);
- return NULL;
- }
- INIT_LIST_HEAD(&timeri->open_list);
- INIT_LIST_HEAD(&timeri->active_list);
- INIT_LIST_HEAD(&timeri->ack_list);
- INIT_LIST_HEAD(&timeri->slave_list_head);
- INIT_LIST_HEAD(&timeri->slave_active_head);
-
- timeri->timer = timer;
- if (timer && !try_module_get(timer->module)) {
- kfree(timeri->owner);
- kfree(timeri);
- return NULL;
- }
-
- return timeri;
-}
-
-/*
- * find a timer instance from the given timer id
- */
-static struct snd_timer *snd_timer_find(struct snd_timer_id *tid)
-{
- struct snd_timer *timer = NULL;
-
- list_for_each_entry(timer, &snd_timer_list, device_list) {
- if (timer->tmr_class != tid->dev_class)
- continue;
- if ((timer->tmr_class == SNDRV_TIMER_CLASS_CARD ||
- timer->tmr_class == SNDRV_TIMER_CLASS_PCM) &&
- (timer->card == NULL ||
- timer->card->number != tid->card))
- continue;
- if (timer->tmr_device != tid->device)
- continue;
- if (timer->tmr_subdevice != tid->subdevice)
- continue;
- return timer;
- }
- return NULL;
-}
-
-#ifdef CONFIG_MODULES
-
-static void snd_timer_request(struct snd_timer_id *tid)
-{
- switch (tid->dev_class) {
- case SNDRV_TIMER_CLASS_GLOBAL:
- if (tid->device < timer_limit)
- request_module("snd-timer-%i", tid->device);
- break;
- case SNDRV_TIMER_CLASS_CARD:
- case SNDRV_TIMER_CLASS_PCM:
- if (tid->card < snd_ecards_limit)
- request_module("snd-card-%i", tid->card);
- break;
- default:
- break;
- }
-}
-
-#endif
-
-/*
- * look for a master instance matching with the slave id of the given slave.
- * when found, relink the open_link of the slave.
- *
- * call this with register_mutex down.
- */
-static void snd_timer_check_slave(struct snd_timer_instance *slave)
-{
- struct snd_timer *timer;
- struct snd_timer_instance *master;
-
- /* FIXME: it's really dumb to look up all entries.. */
- list_for_each_entry(timer, &snd_timer_list, device_list) {
- list_for_each_entry(master, &timer->open_list_head, open_list) {
- if (slave->slave_class == master->slave_class &&
- slave->slave_id == master->slave_id) {
- list_move_tail(&slave->open_list,
- &master->slave_list_head);
- spin_lock_irq(&slave_active_lock);
- slave->master = master;
- slave->timer = master->timer;
- spin_unlock_irq(&slave_active_lock);
- return;
- }
- }
- }
-}
-
-/*
- * look for slave instances matching with the slave id of the given master.
- * when found, relink the open_link of slaves.
- *
- * call this with register_mutex down.
- */
-static void snd_timer_check_master(struct snd_timer_instance *master)
-{
- struct snd_timer_instance *slave, *tmp;
-
- /* check all pending slaves */
- list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) {
- if (slave->slave_class == master->slave_class &&
- slave->slave_id == master->slave_id) {
- list_move_tail(&slave->open_list, &master->slave_list_head);
- spin_lock_irq(&slave_active_lock);
- slave->master = master;
- slave->timer = master->timer;
- if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
- list_add_tail(&slave->active_list,
- &master->slave_active_head);
- spin_unlock_irq(&slave_active_lock);
- }
- }
-}
-
-/*
- * open a timer instance
- * when opening a master, the slave id must be here given.
- */
-int snd_timer_open(struct snd_timer_instance **ti,
- char *owner, struct snd_timer_id *tid,
- unsigned int slave_id)
-{
- struct snd_timer *timer;
- struct snd_timer_instance *timeri = NULL;
-
- if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) {
- /* open a slave instance */
- if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE ||
- tid->dev_sclass > SNDRV_TIMER_SCLASS_OSS_SEQUENCER) {
- snd_printd("invalid slave class %i\n", tid->dev_sclass);
- return -EINVAL;
- }
- mutex_lock(&register_mutex);
- timeri = snd_timer_instance_new(owner, NULL);
- if (!timeri) {
- mutex_unlock(&register_mutex);
- return -ENOMEM;
- }
- timeri->slave_class = tid->dev_sclass;
- timeri->slave_id = tid->device;
- timeri->flags |= SNDRV_TIMER_IFLG_SLAVE;
- list_add_tail(&timeri->open_list, &snd_timer_slave_list);
- snd_timer_check_slave(timeri);
- mutex_unlock(&register_mutex);
- *ti = timeri;
- return 0;
- }
-
- /* open a master instance */
- mutex_lock(&register_mutex);
- timer = snd_timer_find(tid);
-#ifdef CONFIG_MODULES
- if (!timer) {
- mutex_unlock(&register_mutex);
- snd_timer_request(tid);
- mutex_lock(&register_mutex);
- timer = snd_timer_find(tid);
- }
-#endif
- if (!timer) {
- mutex_unlock(&register_mutex);
- return -ENODEV;
- }
- if (!list_empty(&timer->open_list_head)) {
- timeri = list_entry(timer->open_list_head.next,
- struct snd_timer_instance, open_list);
- if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) {
- mutex_unlock(&register_mutex);
- return -EBUSY;
- }
- }
- timeri = snd_timer_instance_new(owner, timer);
- if (!timeri) {
- mutex_unlock(&register_mutex);
- return -ENOMEM;
- }
- timeri->slave_class = tid->dev_sclass;
- timeri->slave_id = slave_id;
- if (list_empty(&timer->open_list_head) && timer->hw.open)
- timer->hw.open(timer);
- list_add_tail(&timeri->open_list, &timer->open_list_head);
- snd_timer_check_master(timeri);
- mutex_unlock(&register_mutex);
- *ti = timeri;
- return 0;
-}
-
-static int _snd_timer_stop(struct snd_timer_instance *timeri,
- int keep_flag, int event);
-
-/*
- * close a timer instance
- */
-int snd_timer_close(struct snd_timer_instance *timeri)
-{
- struct snd_timer *timer = NULL;
- struct snd_timer_instance *slave, *tmp;
-
- if (snd_BUG_ON(!timeri))
- return -ENXIO;
-
- /* force to stop the timer */
- snd_timer_stop(timeri);
-
- if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
- /* wait, until the active callback is finished */
- spin_lock_irq(&slave_active_lock);
- while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
- spin_unlock_irq(&slave_active_lock);
- udelay(10);
- spin_lock_irq(&slave_active_lock);
- }
- spin_unlock_irq(&slave_active_lock);
- mutex_lock(&register_mutex);
- list_del(&timeri->open_list);
- mutex_unlock(&register_mutex);
- } else {
- timer = timeri->timer;
- if (snd_BUG_ON(!timer))
- goto out;
- /* wait, until the active callback is finished */
- spin_lock_irq(&timer->lock);
- while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
- spin_unlock_irq(&timer->lock);
- udelay(10);
- spin_lock_irq(&timer->lock);
- }
- spin_unlock_irq(&timer->lock);
- mutex_lock(&register_mutex);
- list_del(&timeri->open_list);
- if (timer && list_empty(&timer->open_list_head) &&
- timer->hw.close)
- timer->hw.close(timer);
- /* remove slave links */
- list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
- open_list) {
- spin_lock_irq(&slave_active_lock);
- _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
- list_move_tail(&slave->open_list, &snd_timer_slave_list);
- slave->master = NULL;
- slave->timer = NULL;
- spin_unlock_irq(&slave_active_lock);
- }
- mutex_unlock(&register_mutex);
- }
- out:
- if (timeri->private_free)
- timeri->private_free(timeri);
- kfree(timeri->owner);
- kfree(timeri);
- if (timer)
- module_put(timer->module);
- return 0;
-}
-
-unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
-{
- struct snd_timer * timer;
-
- if (timeri == NULL)
- return 0;
- if ((timer = timeri->timer) != NULL) {
- if (timer->hw.c_resolution)
- return timer->hw.c_resolution(timer);
- return timer->hw.resolution;
- }
- return 0;
-}
-
-static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
-{
- struct snd_timer *timer;
- unsigned long flags;
- unsigned long resolution = 0;
- struct snd_timer_instance *ts;
- struct timespec tstamp;
-
- if (timer_tstamp_monotonic)
- do_posix_clock_monotonic_gettime(&tstamp);
- else
- getnstimeofday(&tstamp);
- if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
- event > SNDRV_TIMER_EVENT_PAUSE))
- return;
- if (event == SNDRV_TIMER_EVENT_START ||
- event == SNDRV_TIMER_EVENT_CONTINUE)
- resolution = snd_timer_resolution(ti);
- if (ti->ccallback)
- ti->ccallback(ti, event, &tstamp, resolution);
- if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
- return;
- timer = ti->timer;
- if (timer == NULL)
- return;
- if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
- return;
- spin_lock_irqsave(&timer->lock, flags);
- list_for_each_entry(ts, &ti->slave_active_head, active_list)
- if (ts->ccallback)
- ts->ccallback(ti, event + 100, &tstamp, resolution);
- spin_unlock_irqrestore(&timer->lock, flags);
-}
-
-static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri,
- unsigned long sticks)
-{
- list_move_tail(&timeri->active_list, &timer->active_list_head);
- if (timer->running) {
- if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
- goto __start_now;
- timer->flags |= SNDRV_TIMER_FLG_RESCHED;
- timeri->flags |= SNDRV_TIMER_IFLG_START;
- return 1; /* delayed start */
- } else {
- timer->sticks = sticks;
- timer->hw.start(timer);
- __start_now:
- timer->running++;
- timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
- return 0;
- }
-}
-
-static int snd_timer_start_slave(struct snd_timer_instance *timeri)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&slave_active_lock, flags);
- timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
- if (timeri->master)
- list_add_tail(&timeri->active_list,
- &timeri->master->slave_active_head);
- spin_unlock_irqrestore(&slave_active_lock, flags);
- return 1; /* delayed start */
-}
-
-/*
- * start the timer instance
- */
-int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
-{
- struct snd_timer *timer;
- int result = -EINVAL;
- unsigned long flags;
-
- if (timeri == NULL || ticks < 1)
- return -EINVAL;
- if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
- result = snd_timer_start_slave(timeri);
- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
- return result;
- }
- timer = timeri->timer;
- if (timer == NULL)
- return -EINVAL;
- spin_lock_irqsave(&timer->lock, flags);
- timeri->ticks = timeri->cticks = ticks;
- timeri->pticks = 0;
- result = snd_timer_start1(timer, timeri, ticks);
- spin_unlock_irqrestore(&timer->lock, flags);
- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
- return result;
-}
-
-static int _snd_timer_stop(struct snd_timer_instance * timeri,
- int keep_flag, int event)
-{
- struct snd_timer *timer;
- unsigned long flags;
-
- if (snd_BUG_ON(!timeri))
- return -ENXIO;
-
- if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
- if (!keep_flag) {
- spin_lock_irqsave(&slave_active_lock, flags);
- timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
- spin_unlock_irqrestore(&slave_active_lock, flags);
- }
- goto __end;
- }
- timer = timeri->timer;
- if (!timer)
- return -EINVAL;
- spin_lock_irqsave(&timer->lock, flags);
- list_del_init(&timeri->ack_list);
- list_del_init(&timeri->active_list);
- if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
- !(--timer->running)) {
- timer->hw.stop(timer);
- if (timer->flags & SNDRV_TIMER_FLG_RESCHED) {
- timer->flags &= ~SNDRV_TIMER_FLG_RESCHED;
- snd_timer_reschedule(timer, 0);
- if (timer->flags & SNDRV_TIMER_FLG_CHANGE) {
- timer->flags &= ~SNDRV_TIMER_FLG_CHANGE;
- timer->hw.start(timer);
- }
- }
- }
- if (!keep_flag)
- timeri->flags &=
- ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
- spin_unlock_irqrestore(&timer->lock, flags);
- __end:
- if (event != SNDRV_TIMER_EVENT_RESOLUTION)
- snd_timer_notify1(timeri, event);
- return 0;
-}
-
-/*
- * stop the timer instance.
- *
- * do not call this from the timer callback!
- */
-int snd_timer_stop(struct snd_timer_instance *timeri)
-{
- struct snd_timer *timer;
- unsigned long flags;
- int err;
-
- err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP);
- if (err < 0)
- return err;
- timer = timeri->timer;
- if (!timer)
- return -EINVAL;
- spin_lock_irqsave(&timer->lock, flags);
- timeri->cticks = timeri->ticks;
- timeri->pticks = 0;
- spin_unlock_irqrestore(&timer->lock, flags);
- return 0;
-}
-
-/*
- * start again.. the tick is kept.
- */
-int snd_timer_continue(struct snd_timer_instance *timeri)
-{
- struct snd_timer *timer;
- int result = -EINVAL;
- unsigned long flags;
-
- if (timeri == NULL)
- return result;
- if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
- return snd_timer_start_slave(timeri);
- timer = timeri->timer;
- if (! timer)
- return -EINVAL;
- spin_lock_irqsave(&timer->lock, flags);
- if (!timeri->cticks)
- timeri->cticks = 1;
- timeri->pticks = 0;
- result = snd_timer_start1(timer, timeri, timer->sticks);
- spin_unlock_irqrestore(&timer->lock, flags);
- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
- return result;
-}
-
-/*
- * pause.. remember the ticks left
- */
-int snd_timer_pause(struct snd_timer_instance * timeri)
-{
- return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE);
-}
-
-/*
- * reschedule the timer
- *
- * start pending instances and check the scheduling ticks.
- * when the scheduling ticks is changed set CHANGE flag to reprogram the timer.
- */
-static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left)
-{
- struct snd_timer_instance *ti;
- unsigned long ticks = ~0UL;
-
- list_for_each_entry(ti, &timer->active_list_head, active_list) {
- if (ti->flags & SNDRV_TIMER_IFLG_START) {
- ti->flags &= ~SNDRV_TIMER_IFLG_START;
- ti->flags |= SNDRV_TIMER_IFLG_RUNNING;
- timer->running++;
- }
- if (ti->flags & SNDRV_TIMER_IFLG_RUNNING) {
- if (ticks > ti->cticks)
- ticks = ti->cticks;
- }
- }
- if (ticks == ~0UL) {
- timer->flags &= ~SNDRV_TIMER_FLG_RESCHED;
- return;
- }
- if (ticks > timer->hw.ticks)
- ticks = timer->hw.ticks;
- if (ticks_left != ticks)
- timer->flags |= SNDRV_TIMER_FLG_CHANGE;
- timer->sticks = ticks;
-}
-
-/*
- * timer tasklet
- *
- */
-static void snd_timer_tasklet(unsigned long arg)
-{
- struct snd_timer *timer = (struct snd_timer *) arg;
- struct snd_timer_instance *ti;
- struct list_head *p;
- unsigned long resolution, ticks;
- unsigned long flags;
-
- spin_lock_irqsave(&timer->lock, flags);
- /* now process all callbacks */
- while (!list_empty(&timer->sack_list_head)) {
- p = timer->sack_list_head.next; /* get first item */
- ti = list_entry(p, struct snd_timer_instance, ack_list);
-
- /* remove from ack_list and make empty */
- list_del_init(p);
-
- ticks = ti->pticks;
- ti->pticks = 0;
- resolution = ti->resolution;
-
- ti->flags |= SNDRV_TIMER_IFLG_CALLBACK;
- spin_unlock(&timer->lock);
- if (ti->callback)
- ti->callback(ti, resolution, ticks);
- spin_lock(&timer->lock);
- ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
- }
- spin_unlock_irqrestore(&timer->lock, flags);
-}
-
-/*
- * timer interrupt
- *
- * ticks_left is usually equal to timer->sticks.
- *
- */
-void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
-{
- struct snd_timer_instance *ti, *ts, *tmp;
- unsigned long resolution, ticks;
- struct list_head *p, *ack_list_head;
- unsigned long flags;
- int use_tasklet = 0;
-
- if (timer == NULL)
- return;
-
- spin_lock_irqsave(&timer->lock, flags);
-
- /* remember the current resolution */
- if (timer->hw.c_resolution)
- resolution = timer->hw.c_resolution(timer);
- else
- resolution = timer->hw.resolution;
-
- /* loop for all active instances
- * Here we cannot use list_for_each_entry because the active_list of a
- * processed instance is relinked to done_list_head before the callback
- * is called.
- */
- list_for_each_entry_safe(ti, tmp, &timer->active_list_head,
- active_list) {
- if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING))
- continue;
- ti->pticks += ticks_left;
- ti->resolution = resolution;
- if (ti->cticks < ticks_left)
- ti->cticks = 0;
- else
- ti->cticks -= ticks_left;
- if (ti->cticks) /* not expired */
- continue;
- if (ti->flags & SNDRV_TIMER_IFLG_AUTO) {
- ti->cticks = ti->ticks;
- } else {
- ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
- if (--timer->running)
- list_del(&ti->active_list);
- }
- if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
- (ti->flags & SNDRV_TIMER_IFLG_FAST))
- ack_list_head = &timer->ack_list_head;
- else
- ack_list_head = &timer->sack_list_head;
- if (list_empty(&ti->ack_list))
- list_add_tail(&ti->ack_list, ack_list_head);
- list_for_each_entry(ts, &ti->slave_active_head, active_list) {
- ts->pticks = ti->pticks;
- ts->resolution = resolution;
- if (list_empty(&ts->ack_list))
- list_add_tail(&ts->ack_list, ack_list_head);
- }
- }
- if (timer->flags & SNDRV_TIMER_FLG_RESCHED)
- snd_timer_reschedule(timer, timer->sticks);
- if (timer->running) {
- if (timer->hw.flags & SNDRV_TIMER_HW_STOP) {
- timer->hw.stop(timer);
- timer->flags |= SNDRV_TIMER_FLG_CHANGE;
- }
- if (!(timer->hw.flags & SNDRV_TIMER_HW_AUTO) ||
- (timer->flags & SNDRV_TIMER_FLG_CHANGE)) {
- /* restart timer */
- timer->flags &= ~SNDRV_TIMER_FLG_CHANGE;
- timer->hw.start(timer);
- }
- } else {
- timer->hw.stop(timer);
- }
-
- /* now process all fast callbacks */
- while (!list_empty(&timer->ack_list_head)) {
- p = timer->ack_list_head.next; /* get first item */
- ti = list_entry(p, struct snd_timer_instance, ack_list);
-
- /* remove from ack_list and make empty */
- list_del_init(p);
-
- ticks = ti->pticks;
- ti->pticks = 0;
-
- ti->flags |= SNDRV_TIMER_IFLG_CALLBACK;
- spin_unlock(&timer->lock);
- if (ti->callback)
- ti->callback(ti, resolution, ticks);
- spin_lock(&timer->lock);
- ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
- }
-
- /* do we have any slow callbacks? */
- use_tasklet = !list_empty(&timer->sack_list_head);
- spin_unlock_irqrestore(&timer->lock, flags);
-
- if (use_tasklet)
- tasklet_schedule(&timer->task_queue);
-}
-
-/*
-
- */
-
-int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
- struct snd_timer **rtimer)
-{
- struct snd_timer *timer;
- int err;
- static struct snd_device_ops ops = {
- .dev_free = snd_timer_dev_free,
- .dev_register = snd_timer_dev_register,
- .dev_disconnect = snd_timer_dev_disconnect,
- };
-
- if (snd_BUG_ON(!tid))
- return -EINVAL;
- if (rtimer)
- *rtimer = NULL;
- timer = kzalloc(sizeof(*timer), GFP_KERNEL);
- if (timer == NULL) {
- snd_printk(KERN_ERR "timer: cannot allocate\n");
- return -ENOMEM;
- }
- timer->tmr_class = tid->dev_class;
- timer->card = card;
- timer->tmr_device = tid->device;
- timer->tmr_subdevice = tid->subdevice;
- if (id)
- strlcpy(timer->id, id, sizeof(timer->id));
- INIT_LIST_HEAD(&timer->device_list);
- INIT_LIST_HEAD(&timer->open_list_head);
- INIT_LIST_HEAD(&timer->active_list_head);
- INIT_LIST_HEAD(&timer->ack_list_head);
- INIT_LIST_HEAD(&timer->sack_list_head);
- spin_lock_init(&timer->lock);
- tasklet_init(&timer->task_queue, snd_timer_tasklet,
- (unsigned long)timer);
- if (card != NULL) {
- timer->module = card->module;
- err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops);
- if (err < 0) {
- snd_timer_free(timer);
- return err;
- }
- }
- if (rtimer)
- *rtimer = timer;
- return 0;
-}
-
-static int snd_timer_free(struct snd_timer *timer)
-{
- if (!timer)
- return 0;
-
- mutex_lock(&register_mutex);
- if (! list_empty(&timer->open_list_head)) {
- struct list_head *p, *n;
- struct snd_timer_instance *ti;
- snd_printk(KERN_WARNING "timer %p is busy?\n", timer);
- list_for_each_safe(p, n, &timer->open_list_head) {
- list_del_init(p);
- ti = list_entry(p, struct snd_timer_instance, open_list);
- ti->timer = NULL;
- }
- }
- list_del(&timer->device_list);
- mutex_unlock(&register_mutex);
-
- if (timer->private_free)
- timer->private_free(timer);
- kfree(timer);
- return 0;
-}
-
-static int snd_timer_dev_free(struct snd_device *device)
-{
- struct snd_timer *timer = device->device_data;
- return snd_timer_free(timer);
-}
-
-static int snd_timer_dev_register(struct snd_device *dev)
-{
- struct snd_timer *timer = dev->device_data;
- struct snd_timer *timer1;
-
- if (snd_BUG_ON(!timer || !timer->hw.start || !timer->hw.stop))
- return -ENXIO;
- if (!(timer->hw.flags & SNDRV_TIMER_HW_SLAVE) &&
- !timer->hw.resolution && timer->hw.c_resolution == NULL)
- return -EINVAL;
-
- mutex_lock(&register_mutex);
- list_for_each_entry(timer1, &snd_timer_list, device_list) {
- if (timer1->tmr_class > timer->tmr_class)
- break;
- if (timer1->tmr_class < timer->tmr_class)
- continue;
- if (timer1->card && timer->card) {
- if (timer1->card->number > timer->card->number)
- break;
- if (timer1->card->number < timer->card->number)
- continue;
- }
- if (timer1->tmr_device > timer->tmr_device)
- break;
- if (timer1->tmr_device < timer->tmr_device)
- continue;
- if (timer1->tmr_subdevice > timer->tmr_subdevice)
- break;
- if (timer1->tmr_subdevice < timer->tmr_subdevice)
- continue;
- /* conflicts.. */
- mutex_unlock(&register_mutex);
- return -EBUSY;
- }
- list_add_tail(&timer->device_list, &timer1->device_list);
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-static int snd_timer_dev_disconnect(struct snd_device *device)
-{
- struct snd_timer *timer = device->device_data;
- mutex_lock(&register_mutex);
- list_del_init(&timer->device_list);
- mutex_unlock(&register_mutex);
- return 0;
-}
-
-void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp)
-{
- unsigned long flags;
- unsigned long resolution = 0;
- struct snd_timer_instance *ti, *ts;
-
- if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE))
- return;
- if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART ||
- event > SNDRV_TIMER_EVENT_MRESUME))
- return;
- spin_lock_irqsave(&timer->lock, flags);
- if (event == SNDRV_TIMER_EVENT_MSTART ||
- event == SNDRV_TIMER_EVENT_MCONTINUE ||
- event == SNDRV_TIMER_EVENT_MRESUME) {
- if (timer->hw.c_resolution)
- resolution = timer->hw.c_resolution(timer);
- else
- resolution = timer->hw.resolution;
- }
- list_for_each_entry(ti, &timer->active_list_head, active_list) {
- if (ti->ccallback)
- ti->ccallback(ti, event, tstamp, resolution);
- list_for_each_entry(ts, &ti->slave_active_head, active_list)
- if (ts->ccallback)
- ts->ccallback(ts, event, tstamp, resolution);
- }
- spin_unlock_irqrestore(&timer->lock, flags);
-}
-
-/*
- * exported functions for global timers
- */
-int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer)
-{
- struct snd_timer_id tid;
-
- tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL;
- tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
- tid.card = -1;
- tid.device = device;
- tid.subdevice = 0;
- return snd_timer_new(NULL, id, &tid, rtimer);
-}
-
-int snd_timer_global_free(struct snd_timer *timer)
-{
- return snd_timer_free(timer);
-}
-
-int snd_timer_global_register(struct snd_timer *timer)
-{
- struct snd_device dev;
-
- memset(&dev, 0, sizeof(dev));
- dev.device_data = timer;
- return snd_timer_dev_register(&dev);
-}
-
-/*
- * System timer
- */
-
-struct snd_timer_system_private {
- struct timer_list tlist;
- unsigned long last_expires;
- unsigned long last_jiffies;
- unsigned long correction;
-};
-
-static void snd_timer_s_function(unsigned long data)
-{
- struct snd_timer *timer = (struct snd_timer *)data;
- struct snd_timer_system_private *priv = timer->private_data;
- unsigned long jiff = jiffies;
- if (time_after(jiff, priv->last_expires))
- priv->correction += (long)jiff - (long)priv->last_expires;
- snd_timer_interrupt(timer, (long)jiff - (long)priv->last_jiffies);
-}
-
-static int snd_timer_s_start(struct snd_timer * timer)
-{
- struct snd_timer_system_private *priv;
- unsigned long njiff;
-
- priv = (struct snd_timer_system_private *) timer->private_data;
- njiff = (priv->last_jiffies = jiffies);
- if (priv->correction > timer->sticks - 1) {
- priv->correction -= timer->sticks - 1;
- njiff++;
- } else {
- njiff += timer->sticks - priv->correction;
- priv->correction = 0;
- }
- priv->last_expires = priv->tlist.expires = njiff;
- add_timer(&priv->tlist);
- return 0;
-}
-
-static int snd_timer_s_stop(struct snd_timer * timer)
-{
- struct snd_timer_system_private *priv;
- unsigned long jiff;
-
- priv = (struct snd_timer_system_private *) timer->private_data;
- del_timer(&priv->tlist);
- jiff = jiffies;
- if (time_before(jiff, priv->last_expires))
- timer->sticks = priv->last_expires - jiff;
- else
- timer->sticks = 1;
- priv->correction = 0;
- return 0;
-}
-
-static struct snd_timer_hardware snd_timer_system =
-{
- .flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET,
- .resolution = 1000000000L / HZ,
- .ticks = 10000000L,
- .start = snd_timer_s_start,
- .stop = snd_timer_s_stop
-};
-
-static void snd_timer_free_system(struct snd_timer *timer)
-{
- kfree(timer->private_data);
-}
-
-static int snd_timer_register_system(void)
-{
- struct snd_timer *timer;
- struct snd_timer_system_private *priv;
- int err;
-
- err = snd_timer_global_new("system", SNDRV_TIMER_GLOBAL_SYSTEM, &timer);
- if (err < 0)
- return err;
- strcpy(timer->name, "system timer");
- timer->hw = snd_timer_system;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL) {
- snd_timer_free(timer);
- return -ENOMEM;
- }
- init_timer(&priv->tlist);
- priv->tlist.function = snd_timer_s_function;
- priv->tlist.data = (unsigned long) timer;
- timer->private_data = priv;
- timer->private_free = snd_timer_free_system;
- return snd_timer_global_register(timer);
-}
-
-#ifdef CONFIG_PROC_FS
-/*
- * Info interface
- */
-
-static void snd_timer_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct snd_timer *timer;
- struct snd_timer_instance *ti;
-
- mutex_lock(&register_mutex);
- list_for_each_entry(timer, &snd_timer_list, device_list) {
- switch (timer->tmr_class) {
- case SNDRV_TIMER_CLASS_GLOBAL:
- snd_iprintf(buffer, "G%i: ", timer->tmr_device);
- break;
- case SNDRV_TIMER_CLASS_CARD:
- snd_iprintf(buffer, "C%i-%i: ",
- timer->card->number, timer->tmr_device);
- break;
- case SNDRV_TIMER_CLASS_PCM:
- snd_iprintf(buffer, "P%i-%i-%i: ", timer->card->number,
- timer->tmr_device, timer->tmr_subdevice);
- break;
- default:
- snd_iprintf(buffer, "?%i-%i-%i-%i: ", timer->tmr_class,
- timer->card ? timer->card->number : -1,
- timer->tmr_device, timer->tmr_subdevice);
- }
- snd_iprintf(buffer, "%s :", timer->name);
- if (timer->hw.resolution)
- snd_iprintf(buffer, " %lu.%03luus (%lu ticks)",
- timer->hw.resolution / 1000,
- timer->hw.resolution % 1000,
- timer->hw.ticks);
- if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
- snd_iprintf(buffer, " SLAVE");
- snd_iprintf(buffer, "\n");
- list_for_each_entry(ti, &timer->open_list_head, open_list)
- snd_iprintf(buffer, " Client %s : %s\n",
- ti->owner ? ti->owner : "unknown",
- ti->flags & (SNDRV_TIMER_IFLG_START |
- SNDRV_TIMER_IFLG_RUNNING)
- ? "running" : "stopped");
- }
- mutex_unlock(&register_mutex);
-}
-
-static struct snd_info_entry *snd_timer_proc_entry;
-
-static void __init snd_timer_proc_init(void)
-{
- struct snd_info_entry *entry;
-
- entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL);
- if (entry != NULL) {
- entry->c.text.read = snd_timer_proc_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- snd_timer_proc_entry = entry;
-}
-
-static void __exit snd_timer_proc_done(void)
-{
- snd_info_free_entry(snd_timer_proc_entry);
-}
-#else /* !CONFIG_PROC_FS */
-#define snd_timer_proc_init()
-#define snd_timer_proc_done()
-#endif
-
-/*
- * USER SPACE interface
- */
-
-static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,
- unsigned long resolution,
- unsigned long ticks)
-{
- struct snd_timer_user *tu = timeri->callback_data;
- struct snd_timer_read *r;
- int prev;
-
- spin_lock(&tu->qlock);
- if (tu->qused > 0) {
- prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
- r = &tu->queue[prev];
- if (r->resolution == resolution) {
- r->ticks += ticks;
- goto __wake;
- }
- }
- if (tu->qused >= tu->queue_size) {
- tu->overrun++;
- } else {
- r = &tu->queue[tu->qtail++];
- tu->qtail %= tu->queue_size;
- r->resolution = resolution;
- r->ticks = ticks;
- tu->qused++;
- }
- __wake:
- spin_unlock(&tu->qlock);
- kill_fasync(&tu->fasync, SIGIO, POLL_IN);
- wake_up(&tu->qchange_sleep);
-}
-
-static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu,
- struct snd_timer_tread *tread)
-{
- if (tu->qused >= tu->queue_size) {
- tu->overrun++;
- } else {
- memcpy(&tu->tqueue[tu->qtail++], tread, sizeof(*tread));
- tu->qtail %= tu->queue_size;
- tu->qused++;
- }
-}
-
-static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
- int event,
- struct timespec *tstamp,
- unsigned long resolution)
-{
- struct snd_timer_user *tu = timeri->callback_data;
- struct snd_timer_tread r1;
- unsigned long flags;
-
- if (event >= SNDRV_TIMER_EVENT_START &&
- event <= SNDRV_TIMER_EVENT_PAUSE)
- tu->tstamp = *tstamp;
- if ((tu->filter & (1 << event)) == 0 || !tu->tread)
- return;
- r1.event = event;
- r1.tstamp = *tstamp;
- r1.val = resolution;
- spin_lock_irqsave(&tu->qlock, flags);
- snd_timer_user_append_to_tqueue(tu, &r1);
- spin_unlock_irqrestore(&tu->qlock, flags);
- kill_fasync(&tu->fasync, SIGIO, POLL_IN);
- wake_up(&tu->qchange_sleep);
-}
-
-static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
- unsigned long resolution,
- unsigned long ticks)
-{
- struct snd_timer_user *tu = timeri->callback_data;
- struct snd_timer_tread *r, r1;
- struct timespec tstamp;
- int prev, append = 0;
-
- memset(&tstamp, 0, sizeof(tstamp));
- spin_lock(&tu->qlock);
- if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) |
- (1 << SNDRV_TIMER_EVENT_TICK))) == 0) {
- spin_unlock(&tu->qlock);
- return;
- }
- if (tu->last_resolution != resolution || ticks > 0) {
- if (timer_tstamp_monotonic)
- do_posix_clock_monotonic_gettime(&tstamp);
- else
- getnstimeofday(&tstamp);
- }
- if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
- tu->last_resolution != resolution) {
- r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
- r1.tstamp = tstamp;
- r1.val = resolution;
- snd_timer_user_append_to_tqueue(tu, &r1);
- tu->last_resolution = resolution;
- append++;
- }
- if ((tu->filter & (1 << SNDRV_TIMER_EVENT_TICK)) == 0)
- goto __wake;
- if (ticks == 0)
- goto __wake;
- if (tu->qused > 0) {
- prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
- r = &tu->tqueue[prev];
- if (r->event == SNDRV_TIMER_EVENT_TICK) {
- r->tstamp = tstamp;
- r->val += ticks;
- append++;
- goto __wake;
- }
- }
- r1.event = SNDRV_TIMER_EVENT_TICK;
- r1.tstamp = tstamp;
- r1.val = ticks;
- snd_timer_user_append_to_tqueue(tu, &r1);
- append++;
- __wake:
- spin_unlock(&tu->qlock);
- if (append == 0)
- return;
- kill_fasync(&tu->fasync, SIGIO, POLL_IN);
- wake_up(&tu->qchange_sleep);
-}
-
-static int snd_timer_user_open(struct inode *inode, struct file *file)
-{
- struct snd_timer_user *tu;
- int err;
-
- err = nonseekable_open(inode, file);
- if (err < 0)
- return err;
-
- tu = kzalloc(sizeof(*tu), GFP_KERNEL);
- if (tu == NULL)
- return -ENOMEM;
- spin_lock_init(&tu->qlock);
- init_waitqueue_head(&tu->qchange_sleep);
- mutex_init(&tu->tread_sem);
- tu->ticks = 1;
- tu->queue_size = 128;
- tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
- GFP_KERNEL);
- if (tu->queue == NULL) {
- kfree(tu);
- return -ENOMEM;
- }
- file->private_data = tu;
- return 0;
-}
-
-static int snd_timer_user_release(struct inode *inode, struct file *file)
-{
- struct snd_timer_user *tu;
-
- if (file->private_data) {
- tu = file->private_data;
- file->private_data = NULL;
- if (tu->timeri)
- snd_timer_close(tu->timeri);
- kfree(tu->queue);
- kfree(tu->tqueue);
- kfree(tu);
- }
- return 0;
-}
-
-static void snd_timer_user_zero_id(struct snd_timer_id *id)
-{
- id->dev_class = SNDRV_TIMER_CLASS_NONE;
- id->dev_sclass = SNDRV_TIMER_SCLASS_NONE;
- id->card = -1;
- id->device = -1;
- id->subdevice = -1;
-}
-
-static void snd_timer_user_copy_id(struct snd_timer_id *id, struct snd_timer *timer)
-{
- id->dev_class = timer->tmr_class;
- id->dev_sclass = SNDRV_TIMER_SCLASS_NONE;
- id->card = timer->card ? timer->card->number : -1;
- id->device = timer->tmr_device;
- id->subdevice = timer->tmr_subdevice;
-}
-
-static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
-{
- struct snd_timer_id id;
- struct snd_timer *timer;
- struct list_head *p;
-
- if (copy_from_user(&id, _tid, sizeof(id)))
- return -EFAULT;
- mutex_lock(&register_mutex);
- if (id.dev_class < 0) { /* first item */
- if (list_empty(&snd_timer_list))
- snd_timer_user_zero_id(&id);
- else {
- timer = list_entry(snd_timer_list.next,
- struct snd_timer, device_list);
- snd_timer_user_copy_id(&id, timer);
- }
- } else {
- switch (id.dev_class) {
- case SNDRV_TIMER_CLASS_GLOBAL:
- id.device = id.device < 0 ? 0 : id.device + 1;
- list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, struct snd_timer, device_list);
- if (timer->tmr_class > SNDRV_TIMER_CLASS_GLOBAL) {
- snd_timer_user_copy_id(&id, timer);
- break;
- }
- if (timer->tmr_device >= id.device) {
- snd_timer_user_copy_id(&id, timer);
- break;
- }
- }
- if (p == &snd_timer_list)
- snd_timer_user_zero_id(&id);
- break;
- case SNDRV_TIMER_CLASS_CARD:
- case SNDRV_TIMER_CLASS_PCM:
- if (id.card < 0) {
- id.card = 0;
- } else {
- if (id.card < 0) {
- id.card = 0;
- } else {
- if (id.device < 0) {
- id.device = 0;
- } else {
- if (id.subdevice < 0) {
- id.subdevice = 0;
- } else {
- id.subdevice++;
- }
- }
- }
- }
- list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, struct snd_timer, device_list);
- if (timer->tmr_class > id.dev_class) {
- snd_timer_user_copy_id(&id, timer);
- break;
- }
- if (timer->tmr_class < id.dev_class)
- continue;
- if (timer->card->number > id.card) {
- snd_timer_user_copy_id(&id, timer);
- break;
- }
- if (timer->card->number < id.card)
- continue;
- if (timer->tmr_device > id.device) {
- snd_timer_user_copy_id(&id, timer);
- break;
- }
- if (timer->tmr_device < id.device)
- continue;
- if (timer->tmr_subdevice > id.subdevice) {
- snd_timer_user_copy_id(&id, timer);
- break;
- }
- if (timer->tmr_subdevice < id.subdevice)
- continue;
- snd_timer_user_copy_id(&id, timer);
- break;
- }
- if (p == &snd_timer_list)
- snd_timer_user_zero_id(&id);
- break;
- default:
- snd_timer_user_zero_id(&id);
- }
- }
- mutex_unlock(&register_mutex);
- if (copy_to_user(_tid, &id, sizeof(*_tid)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_timer_user_ginfo(struct file *file,
- struct snd_timer_ginfo __user *_ginfo)
-{
- struct snd_timer_ginfo *ginfo;
- struct snd_timer_id tid;
- struct snd_timer *t;
- struct list_head *p;
- int err = 0;
-
- ginfo = memdup_user(_ginfo, sizeof(*ginfo));
- if (IS_ERR(ginfo))
- return PTR_ERR(ginfo);
-
- tid = ginfo->tid;
- memset(ginfo, 0, sizeof(*ginfo));
- ginfo->tid = tid;
- mutex_lock(&register_mutex);
- t = snd_timer_find(&tid);
- if (t != NULL) {
- ginfo->card = t->card ? t->card->number : -1;
- if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
- ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(ginfo->id, t->id, sizeof(ginfo->id));
- strlcpy(ginfo->name, t->name, sizeof(ginfo->name));
- ginfo->resolution = t->hw.resolution;
- if (t->hw.resolution_min > 0) {
- ginfo->resolution_min = t->hw.resolution_min;
- ginfo->resolution_max = t->hw.resolution_max;
- }
- list_for_each(p, &t->open_list_head) {
- ginfo->clients++;
- }
- } else {
- err = -ENODEV;
- }
- mutex_unlock(&register_mutex);
- if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo)))
- err = -EFAULT;
- kfree(ginfo);
- return err;
-}
-
-static int snd_timer_user_gparams(struct file *file,
- struct snd_timer_gparams __user *_gparams)
-{
- struct snd_timer_gparams gparams;
- struct snd_timer *t;
- int err;
-
- if (copy_from_user(&gparams, _gparams, sizeof(gparams)))
- return -EFAULT;
- mutex_lock(&register_mutex);
- t = snd_timer_find(&gparams.tid);
- if (!t) {
- err = -ENODEV;
- goto _error;
- }
- if (!list_empty(&t->open_list_head)) {
- err = -EBUSY;
- goto _error;
- }
- if (!t->hw.set_period) {
- err = -ENOSYS;
- goto _error;
- }
- err = t->hw.set_period(t, gparams.period_num, gparams.period_den);
-_error:
- mutex_unlock(&register_mutex);
- return err;
-}
-
-static int snd_timer_user_gstatus(struct file *file,
- struct snd_timer_gstatus __user *_gstatus)
-{
- struct snd_timer_gstatus gstatus;
- struct snd_timer_id tid;
- struct snd_timer *t;
- int err = 0;
-
- if (copy_from_user(&gstatus, _gstatus, sizeof(gstatus)))
- return -EFAULT;
- tid = gstatus.tid;
- memset(&gstatus, 0, sizeof(gstatus));
- gstatus.tid = tid;
- mutex_lock(&register_mutex);
- t = snd_timer_find(&tid);
- if (t != NULL) {
- if (t->hw.c_resolution)
- gstatus.resolution = t->hw.c_resolution(t);
- else
- gstatus.resolution = t->hw.resolution;
- if (t->hw.precise_resolution) {
- t->hw.precise_resolution(t, &gstatus.resolution_num,
- &gstatus.resolution_den);
- } else {
- gstatus.resolution_num = gstatus.resolution;
- gstatus.resolution_den = 1000000000uL;
- }
- } else {
- err = -ENODEV;
- }
- mutex_unlock(&register_mutex);
- if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus)))
- err = -EFAULT;
- return err;
-}
-
-static int snd_timer_user_tselect(struct file *file,
- struct snd_timer_select __user *_tselect)
-{
- struct snd_timer_user *tu;
- struct snd_timer_select tselect;
- char str[32];
- int err = 0;
-
- tu = file->private_data;
- mutex_lock(&tu->tread_sem);
- if (tu->timeri) {
- snd_timer_close(tu->timeri);
- tu->timeri = NULL;
- }
- if (copy_from_user(&tselect, _tselect, sizeof(tselect))) {
- err = -EFAULT;
- goto __err;
- }
- sprintf(str, "application %i", current->pid);
- if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
- tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
- err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid);
- if (err < 0)
- goto __err;
-
- kfree(tu->queue);
- tu->queue = NULL;
- kfree(tu->tqueue);
- tu->tqueue = NULL;
- if (tu->tread) {
- tu->tqueue = kmalloc(tu->queue_size * sizeof(struct snd_timer_tread),
- GFP_KERNEL);
- if (tu->tqueue == NULL)
- err = -ENOMEM;
- } else {
- tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
- GFP_KERNEL);
- if (tu->queue == NULL)
- err = -ENOMEM;
- }
-
- if (err < 0) {
- snd_timer_close(tu->timeri);
- tu->timeri = NULL;
- } else {
- tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
- tu->timeri->callback = tu->tread
- ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
- tu->timeri->ccallback = snd_timer_user_ccallback;
- tu->timeri->callback_data = (void *)tu;
- }
-
- __err:
- mutex_unlock(&tu->tread_sem);
- return err;
-}
-
-static int snd_timer_user_info(struct file *file,
- struct snd_timer_info __user *_info)
-{
- struct snd_timer_user *tu;
- struct snd_timer_info *info;
- struct snd_timer *t;
- int err = 0;
-
- tu = file->private_data;
- if (!tu->timeri)
- return -EBADFD;
- t = tu->timeri->timer;
- if (!t)
- return -EBADFD;
-
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (! info)
- return -ENOMEM;
- info->card = t->card ? t->card->number : -1;
- if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
- info->flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(info->id, t->id, sizeof(info->id));
- strlcpy(info->name, t->name, sizeof(info->name));
- info->resolution = t->hw.resolution;
- if (copy_to_user(_info, info, sizeof(*_info)))
- err = -EFAULT;
- kfree(info);
- return err;
-}
-
-static int snd_timer_user_params(struct file *file,
- struct snd_timer_params __user *_params)
-{
- struct snd_timer_user *tu;
- struct snd_timer_params params;
- struct snd_timer *t;
- struct snd_timer_read *tr;
- struct snd_timer_tread *ttr;
- int err;
-
- tu = file->private_data;
- if (!tu->timeri)
- return -EBADFD;
- t = tu->timeri->timer;
- if (!t)
- return -EBADFD;
- if (copy_from_user(&params, _params, sizeof(params)))
- return -EFAULT;
- if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) {
- err = -EINVAL;
- goto _end;
- }
- if (params.queue_size > 0 &&
- (params.queue_size < 32 || params.queue_size > 1024)) {
- err = -EINVAL;
- goto _end;
- }
- if (params.filter & ~((1<<SNDRV_TIMER_EVENT_RESOLUTION)|
- (1<<SNDRV_TIMER_EVENT_TICK)|
- (1<<SNDRV_TIMER_EVENT_START)|
- (1<<SNDRV_TIMER_EVENT_STOP)|
- (1<<SNDRV_TIMER_EVENT_CONTINUE)|
- (1<<SNDRV_TIMER_EVENT_PAUSE)|
- (1<<SNDRV_TIMER_EVENT_SUSPEND)|
- (1<<SNDRV_TIMER_EVENT_RESUME)|
- (1<<SNDRV_TIMER_EVENT_MSTART)|
- (1<<SNDRV_TIMER_EVENT_MSTOP)|
- (1<<SNDRV_TIMER_EVENT_MCONTINUE)|
- (1<<SNDRV_TIMER_EVENT_MPAUSE)|
- (1<<SNDRV_TIMER_EVENT_MSUSPEND)|
- (1<<SNDRV_TIMER_EVENT_MRESUME))) {
- err = -EINVAL;
- goto _end;
- }
- snd_timer_stop(tu->timeri);
- spin_lock_irq(&t->lock);
- tu->timeri->flags &= ~(SNDRV_TIMER_IFLG_AUTO|
- SNDRV_TIMER_IFLG_EXCLUSIVE|
- SNDRV_TIMER_IFLG_EARLY_EVENT);
- if (params.flags & SNDRV_TIMER_PSFLG_AUTO)
- tu->timeri->flags |= SNDRV_TIMER_IFLG_AUTO;
- if (params.flags & SNDRV_TIMER_PSFLG_EXCLUSIVE)
- tu->timeri->flags |= SNDRV_TIMER_IFLG_EXCLUSIVE;
- if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT)
- tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT;
- spin_unlock_irq(&t->lock);
- if (params.queue_size > 0 &&
- (unsigned int)tu->queue_size != params.queue_size) {
- if (tu->tread) {
- ttr = kmalloc(params.queue_size * sizeof(*ttr),
- GFP_KERNEL);
- if (ttr) {
- kfree(tu->tqueue);
- tu->queue_size = params.queue_size;
- tu->tqueue = ttr;
- }
- } else {
- tr = kmalloc(params.queue_size * sizeof(*tr),
- GFP_KERNEL);
- if (tr) {
- kfree(tu->queue);
- tu->queue_size = params.queue_size;
- tu->queue = tr;
- }
- }
- }
- tu->qhead = tu->qtail = tu->qused = 0;
- if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
- if (tu->tread) {
- struct snd_timer_tread tread;
- tread.event = SNDRV_TIMER_EVENT_EARLY;
- tread.tstamp.tv_sec = 0;
- tread.tstamp.tv_nsec = 0;
- tread.val = 0;
- snd_timer_user_append_to_tqueue(tu, &tread);
- } else {
- struct snd_timer_read *r = &tu->queue[0];
- r->resolution = 0;
- r->ticks = 0;
- tu->qused++;
- tu->qtail++;
- }
- }
- tu->filter = params.filter;
- tu->ticks = params.ticks;
- err = 0;
- _end:
- if (copy_to_user(_params, &params, sizeof(params)))
- return -EFAULT;
- return err;
-}
-
-static int snd_timer_user_status(struct file *file,
- struct snd_timer_status __user *_status)
-{
- struct snd_timer_user *tu;
- struct snd_timer_status status;
-
- tu = file->private_data;
- if (!tu->timeri)
- return -EBADFD;
- memset(&status, 0, sizeof(status));
- status.tstamp = tu->tstamp;
- status.resolution = snd_timer_resolution(tu->timeri);
- status.lost = tu->timeri->lost;
- status.overrun = tu->overrun;
- spin_lock_irq(&tu->qlock);
- status.queue = tu->qused;
- spin_unlock_irq(&tu->qlock);
- if (copy_to_user(_status, &status, sizeof(status)))
- return -EFAULT;
- return 0;
-}
-
-static int snd_timer_user_start(struct file *file)
-{
- int err;
- struct snd_timer_user *tu;
-
- tu = file->private_data;
- if (!tu->timeri)
- return -EBADFD;
- snd_timer_stop(tu->timeri);
- tu->timeri->lost = 0;
- tu->last_resolution = 0;
- return (err = snd_timer_start(tu->timeri, tu->ticks)) < 0 ? err : 0;
-}
-
-static int snd_timer_user_stop(struct file *file)
-{
- int err;
- struct snd_timer_user *tu;
-
- tu = file->private_data;
- if (!tu->timeri)
- return -EBADFD;
- return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0;
-}
-
-static int snd_timer_user_continue(struct file *file)
-{
- int err;
- struct snd_timer_user *tu;
-
- tu = file->private_data;
- if (!tu->timeri)
- return -EBADFD;
- tu->timeri->lost = 0;
- return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
-}
-
-static int snd_timer_user_pause(struct file *file)
-{
- int err;
- struct snd_timer_user *tu;
-
- tu = file->private_data;
- if (!tu->timeri)
- return -EBADFD;
- return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0;
-}
-
-enum {
- SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20),
- SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21),
- SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22),
- SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
-};
-
-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct snd_timer_user *tu;
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
-
- tu = file->private_data;
- switch (cmd) {
- case SNDRV_TIMER_IOCTL_PVERSION:
- return put_user(SNDRV_TIMER_VERSION, p) ? -EFAULT : 0;
- case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
- return snd_timer_user_next_device(argp);
- case SNDRV_TIMER_IOCTL_TREAD:
- {
- int xarg;
-
- mutex_lock(&tu->tread_sem);
- if (tu->timeri) { /* too late */
- mutex_unlock(&tu->tread_sem);
- return -EBUSY;
- }
- if (get_user(xarg, p)) {
- mutex_unlock(&tu->tread_sem);
- return -EFAULT;
- }
- tu->tread = xarg ? 1 : 0;
- mutex_unlock(&tu->tread_sem);
- return 0;
- }
- case SNDRV_TIMER_IOCTL_GINFO:
- return snd_timer_user_ginfo(file, argp);
- case SNDRV_TIMER_IOCTL_GPARAMS:
- return snd_timer_user_gparams(file, argp);
- case SNDRV_TIMER_IOCTL_GSTATUS:
- return snd_timer_user_gstatus(file, argp);
- case SNDRV_TIMER_IOCTL_SELECT:
- return snd_timer_user_tselect(file, argp);
- case SNDRV_TIMER_IOCTL_INFO:
- return snd_timer_user_info(file, argp);
- case SNDRV_TIMER_IOCTL_PARAMS:
- return snd_timer_user_params(file, argp);
- case SNDRV_TIMER_IOCTL_STATUS:
- return snd_timer_user_status(file, argp);
- case SNDRV_TIMER_IOCTL_START:
- case SNDRV_TIMER_IOCTL_START_OLD:
- return snd_timer_user_start(file);
- case SNDRV_TIMER_IOCTL_STOP:
- case SNDRV_TIMER_IOCTL_STOP_OLD:
- return snd_timer_user_stop(file);
- case SNDRV_TIMER_IOCTL_CONTINUE:
- case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
- return snd_timer_user_continue(file);
- case SNDRV_TIMER_IOCTL_PAUSE:
- case SNDRV_TIMER_IOCTL_PAUSE_OLD:
- return snd_timer_user_pause(file);
- }
- return -ENOTTY;
-}
-
-static int snd_timer_user_fasync(int fd, struct file * file, int on)
-{
- struct snd_timer_user *tu;
-
- tu = file->private_data;
- return fasync_helper(fd, file, on, &tu->fasync);
-}
-
-static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
- size_t count, loff_t *offset)
-{
- struct snd_timer_user *tu;
- long result = 0, unit;
- int err = 0;
-
- tu = file->private_data;
- unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read);
- spin_lock_irq(&tu->qlock);
- while ((long)count - result >= unit) {
- while (!tu->qused) {
- wait_queue_t wait;
-
- if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
- err = -EAGAIN;
- break;
- }
-
- set_current_state(TASK_INTERRUPTIBLE);
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&tu->qchange_sleep, &wait);
-
- spin_unlock_irq(&tu->qlock);
- schedule();
- spin_lock_irq(&tu->qlock);
-
- remove_wait_queue(&tu->qchange_sleep, &wait);
-
- if (signal_pending(current)) {
- err = -ERESTARTSYS;
- break;
- }
- }
-
- spin_unlock_irq(&tu->qlock);
- if (err < 0)
- goto _error;
-
- if (tu->tread) {
- if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
- sizeof(struct snd_timer_tread))) {
- err = -EFAULT;
- goto _error;
- }
- } else {
- if (copy_to_user(buffer, &tu->queue[tu->qhead++],
- sizeof(struct snd_timer_read))) {
- err = -EFAULT;
- goto _error;
- }
- }
-
- tu->qhead %= tu->queue_size;
-
- result += unit;
- buffer += unit;
-
- spin_lock_irq(&tu->qlock);
- tu->qused--;
- }
- spin_unlock_irq(&tu->qlock);
- _error:
- return result > 0 ? result : err;
-}
-
-static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
-{
- unsigned int mask;
- struct snd_timer_user *tu;
-
- tu = file->private_data;
-
- poll_wait(file, &tu->qchange_sleep, wait);
-
- mask = 0;
- if (tu->qused)
- mask |= POLLIN | POLLRDNORM;
-
- return mask;
-}
-
-#ifdef CONFIG_COMPAT
-#include "timer_compat.c"
-#else
-#define snd_timer_user_ioctl_compat NULL
-#endif
-
-static const struct file_operations snd_timer_f_ops =
-{
- .owner = THIS_MODULE,
- .read = snd_timer_user_read,
- .open = snd_timer_user_open,
- .release = snd_timer_user_release,
- .llseek = no_llseek,
- .poll = snd_timer_user_poll,
- .unlocked_ioctl = snd_timer_user_ioctl,
- .compat_ioctl = snd_timer_user_ioctl_compat,
- .fasync = snd_timer_user_fasync,
-};
-
-/*
- * ENTRY functions
- */
-
-static int __init alsa_timer_init(void)
-{
- int err;
-
-#ifdef SNDRV_OSS_INFO_DEV_TIMERS
- snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1,
- "system timer");
-#endif
-
- if ((err = snd_timer_register_system()) < 0)
- snd_printk(KERN_ERR "unable to register system timer (%i)\n",
- err);
- if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
- &snd_timer_f_ops, NULL, "timer")) < 0)
- snd_printk(KERN_ERR "unable to register timer device (%i)\n",
- err);
- snd_timer_proc_init();
- return 0;
-}
-
-static void __exit alsa_timer_exit(void)
-{
- struct list_head *p, *n;
-
- snd_unregister_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0);
- /* unregister the system timer */
- list_for_each_safe(p, n, &snd_timer_list) {
- struct snd_timer *timer = list_entry(p, struct snd_timer, device_list);
- snd_timer_free(timer);
- }
- snd_timer_proc_done();
-#ifdef SNDRV_OSS_INFO_DEV_TIMERS
- snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1);
-#endif
-}
-
-module_init(alsa_timer_init)
-module_exit(alsa_timer_exit)
-
-EXPORT_SYMBOL(snd_timer_open);
-EXPORT_SYMBOL(snd_timer_close);
-EXPORT_SYMBOL(snd_timer_resolution);
-EXPORT_SYMBOL(snd_timer_start);
-EXPORT_SYMBOL(snd_timer_stop);
-EXPORT_SYMBOL(snd_timer_continue);
-EXPORT_SYMBOL(snd_timer_pause);
-EXPORT_SYMBOL(snd_timer_new);
-EXPORT_SYMBOL(snd_timer_notify);
-EXPORT_SYMBOL(snd_timer_global_new);
-EXPORT_SYMBOL(snd_timer_global_free);
-EXPORT_SYMBOL(snd_timer_global_register);
-EXPORT_SYMBOL(snd_timer_interrupt);
diff --git a/ANDROID_3.4.5/sound/core/timer_compat.c b/ANDROID_3.4.5/sound/core/timer_compat.c
deleted file mode 100644
index e05802ae..00000000
--- a/ANDROID_3.4.5/sound/core/timer_compat.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for timer API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/* This file included from timer.c */
-
-#include <linux/compat.h>
-
-struct snd_timer_info32 {
- u32 flags;
- s32 card;
- unsigned char id[64];
- unsigned char name[80];
- u32 reserved0;
- u32 resolution;
- unsigned char reserved[64];
-};
-
-static int snd_timer_user_info_compat(struct file *file,
- struct snd_timer_info32 __user *_info)
-{
- struct snd_timer_user *tu;
- struct snd_timer_info32 info;
- struct snd_timer *t;
-
- tu = file->private_data;
- if (snd_BUG_ON(!tu->timeri))
- return -ENXIO;
- t = tu->timeri->timer;
- if (snd_BUG_ON(!t))
- return -ENXIO;
- memset(&info, 0, sizeof(info));
- info.card = t->card ? t->card->number : -1;
- if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
- info.flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(info.id, t->id, sizeof(info.id));
- strlcpy(info.name, t->name, sizeof(info.name));
- info.resolution = t->hw.resolution;
- if (copy_to_user(_info, &info, sizeof(*_info)))
- return -EFAULT;
- return 0;
-}
-
-struct snd_timer_status32 {
- struct compat_timespec tstamp;
- u32 resolution;
- u32 lost;
- u32 overrun;
- u32 queue;
- unsigned char reserved[64];
-};
-
-static int snd_timer_user_status_compat(struct file *file,
- struct snd_timer_status32 __user *_status)
-{
- struct snd_timer_user *tu;
- struct snd_timer_status status;
-
- tu = file->private_data;
- if (snd_BUG_ON(!tu->timeri))
- return -ENXIO;
- memset(&status, 0, sizeof(status));
- status.tstamp = tu->tstamp;
- status.resolution = snd_timer_resolution(tu->timeri);
- status.lost = tu->timeri->lost;
- status.overrun = tu->overrun;
- spin_lock_irq(&tu->qlock);
- status.queue = tu->qused;
- spin_unlock_irq(&tu->qlock);
- if (copy_to_user(_status, &status, sizeof(status)))
- return -EFAULT;
- return 0;
-}
-
-/*
- */
-
-enum {
- SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
- SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
-};
-
-static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
-{
- void __user *argp = compat_ptr(arg);
-
- switch (cmd) {
- case SNDRV_TIMER_IOCTL_PVERSION:
- case SNDRV_TIMER_IOCTL_TREAD:
- case SNDRV_TIMER_IOCTL_GINFO:
- case SNDRV_TIMER_IOCTL_GPARAMS:
- case SNDRV_TIMER_IOCTL_GSTATUS:
- case SNDRV_TIMER_IOCTL_SELECT:
- case SNDRV_TIMER_IOCTL_PARAMS:
- case SNDRV_TIMER_IOCTL_START:
- case SNDRV_TIMER_IOCTL_START_OLD:
- case SNDRV_TIMER_IOCTL_STOP:
- case SNDRV_TIMER_IOCTL_STOP_OLD:
- case SNDRV_TIMER_IOCTL_CONTINUE:
- case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
- case SNDRV_TIMER_IOCTL_PAUSE:
- case SNDRV_TIMER_IOCTL_PAUSE_OLD:
- case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
- return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
- case SNDRV_TIMER_IOCTL_INFO32:
- return snd_timer_user_info_compat(file, argp);
- case SNDRV_TIMER_IOCTL_STATUS32:
- return snd_timer_user_status_compat(file, argp);
- }
- return -ENOIOCTLCMD;
-}
diff --git a/ANDROID_3.4.5/sound/core/vmaster.c b/ANDROID_3.4.5/sound/core/vmaster.c
deleted file mode 100644
index 85758613..00000000
--- a/ANDROID_3.4.5/sound/core/vmaster.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Virtual master and slave controls
- *
- * Copyright (c) 2008 by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/tlv.h>
-
-/*
- * a subset of information returned via ctl info callback
- */
-struct link_ctl_info {
- snd_ctl_elem_type_t type; /* value type */
- int count; /* item count */
- int min_val, max_val; /* min, max values */
-};
-
-/*
- * link master - this contains a list of slave controls that are
- * identical types, i.e. info returns the same value type and value
- * ranges, but may have different number of counts.
- *
- * The master control is so far only mono volume/switch for simplicity.
- * The same value will be applied to all slaves.
- */
-struct link_master {
- struct list_head slaves;
- struct link_ctl_info info;
- int val; /* the master value */
- unsigned int tlv[4];
- void (*hook)(void *private_data, int);
- void *hook_private_data;
-};
-
-/*
- * link slave - this contains a slave control element
- *
- * It fakes the control callbacsk with additional attenuation by the
- * master control. A slave may have either one or two channels.
- */
-
-struct link_slave {
- struct list_head list;
- struct link_master *master;
- struct link_ctl_info info;
- int vals[2]; /* current values */
- unsigned int flags;
- struct snd_kcontrol *kctl; /* original kcontrol pointer */
- struct snd_kcontrol slave; /* the copy of original control entry */
-};
-
-static int slave_update(struct link_slave *slave)
-{
- struct snd_ctl_elem_value *uctl;
- int err, ch;
-
- uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
- if (!uctl)
- return -ENOMEM;
- uctl->id = slave->slave.id;
- err = slave->slave.get(&slave->slave, uctl);
- for (ch = 0; ch < slave->info.count; ch++)
- slave->vals[ch] = uctl->value.integer.value[ch];
- kfree(uctl);
- return 0;
-}
-
-/* get the slave ctl info and save the initial values */
-static int slave_init(struct link_slave *slave)
-{
- struct snd_ctl_elem_info *uinfo;
- int err;
-
- if (slave->info.count) {
- /* already initialized */
- if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE)
- return slave_update(slave);
- return 0;
- }
-
- uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
- if (!uinfo)
- return -ENOMEM;
- uinfo->id = slave->slave.id;
- err = slave->slave.info(&slave->slave, uinfo);
- if (err < 0) {
- kfree(uinfo);
- return err;
- }
- slave->info.type = uinfo->type;
- slave->info.count = uinfo->count;
- if (slave->info.count > 2 ||
- (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER &&
- slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) {
- snd_printk(KERN_ERR "invalid slave element\n");
- kfree(uinfo);
- return -EINVAL;
- }
- slave->info.min_val = uinfo->value.integer.min;
- slave->info.max_val = uinfo->value.integer.max;
- kfree(uinfo);
-
- return slave_update(slave);
-}
-
-/* initialize master volume */
-static int master_init(struct link_master *master)
-{
- struct link_slave *slave;
-
- if (master->info.count)
- return 0; /* already initialized */
-
- list_for_each_entry(slave, &master->slaves, list) {
- int err = slave_init(slave);
- if (err < 0)
- return err;
- master->info = slave->info;
- master->info.count = 1; /* always mono */
- /* set full volume as default (= no attenuation) */
- master->val = master->info.max_val;
- if (master->hook)
- master->hook(master->hook_private_data, master->val);
- return 1;
- }
- return -ENOENT;
-}
-
-static int slave_get_val(struct link_slave *slave,
- struct snd_ctl_elem_value *ucontrol)
-{
- int err, ch;
-
- err = slave_init(slave);
- if (err < 0)
- return err;
- for (ch = 0; ch < slave->info.count; ch++)
- ucontrol->value.integer.value[ch] = slave->vals[ch];
- return 0;
-}
-
-static int slave_put_val(struct link_slave *slave,
- struct snd_ctl_elem_value *ucontrol)
-{
- int err, ch, vol;
-
- err = master_init(slave->master);
- if (err < 0)
- return err;
-
- switch (slave->info.type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- for (ch = 0; ch < slave->info.count; ch++)
- ucontrol->value.integer.value[ch] &=
- !!slave->master->val;
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- for (ch = 0; ch < slave->info.count; ch++) {
- /* max master volume is supposed to be 0 dB */
- vol = ucontrol->value.integer.value[ch];
- vol += slave->master->val - slave->master->info.max_val;
- if (vol < slave->info.min_val)
- vol = slave->info.min_val;
- else if (vol > slave->info.max_val)
- vol = slave->info.max_val;
- ucontrol->value.integer.value[ch] = vol;
- }
- break;
- }
- return slave->slave.put(&slave->slave, ucontrol);
-}
-
-/*
- * ctl callbacks for slaves
- */
-static int slave_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
- return slave->slave.info(&slave->slave, uinfo);
-}
-
-static int slave_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
- return slave_get_val(slave, ucontrol);
-}
-
-static int slave_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
- int err, ch, changed = 0;
-
- err = slave_init(slave);
- if (err < 0)
- return err;
- for (ch = 0; ch < slave->info.count; ch++) {
- if (slave->vals[ch] != ucontrol->value.integer.value[ch]) {
- changed = 1;
- slave->vals[ch] = ucontrol->value.integer.value[ch];
- }
- }
- if (!changed)
- return 0;
- return slave_put_val(slave, ucontrol);
-}
-
-static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
- int op_flag, unsigned int size,
- unsigned int __user *tlv)
-{
- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
- /* FIXME: this assumes that the max volume is 0 dB */
- return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv);
-}
-
-static void slave_free(struct snd_kcontrol *kcontrol)
-{
- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
- if (slave->slave.private_free)
- slave->slave.private_free(&slave->slave);
- if (slave->master)
- list_del(&slave->list);
- kfree(slave);
-}
-
-/*
- * Add a slave control to the group with the given master control
- *
- * All slaves must be the same type (returning the same information
- * via info callback). The function doesn't check it, so it's your
- * responsibility.
- *
- * Also, some additional limitations:
- * - at most two channels
- * - logarithmic volume control (dB level), no linear volume
- * - master can only attenuate the volume, no gain
- */
-int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
- unsigned int flags)
-{
- struct link_master *master_link = snd_kcontrol_chip(master);
- struct link_slave *srec;
-
- srec = kzalloc(sizeof(*srec) +
- slave->count * sizeof(*slave->vd), GFP_KERNEL);
- if (!srec)
- return -ENOMEM;
- srec->kctl = slave;
- srec->slave = *slave;
- memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
- srec->master = master_link;
- srec->flags = flags;
-
- /* override callbacks */
- slave->info = slave_info;
- slave->get = slave_get;
- slave->put = slave_put;
- if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)
- slave->tlv.c = slave_tlv_cmd;
- slave->private_data = srec;
- slave->private_free = slave_free;
-
- list_add_tail(&srec->list, &master_link->slaves);
- return 0;
-}
-EXPORT_SYMBOL(_snd_ctl_add_slave);
-
-/*
- * ctl callbacks for master controls
- */
-static int master_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct link_master *master = snd_kcontrol_chip(kcontrol);
- int ret;
-
- ret = master_init(master);
- if (ret < 0)
- return ret;
- uinfo->type = master->info.type;
- uinfo->count = master->info.count;
- uinfo->value.integer.min = master->info.min_val;
- uinfo->value.integer.max = master->info.max_val;
- return 0;
-}
-
-static int master_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct link_master *master = snd_kcontrol_chip(kcontrol);
- int err = master_init(master);
- if (err < 0)
- return err;
- ucontrol->value.integer.value[0] = master->val;
- return 0;
-}
-
-static int master_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct link_master *master = snd_kcontrol_chip(kcontrol);
- struct link_slave *slave;
- struct snd_ctl_elem_value *uval;
- int err, old_val;
-
- err = master_init(master);
- if (err < 0)
- return err;
- old_val = master->val;
- if (ucontrol->value.integer.value[0] == old_val)
- return 0;
-
- uval = kmalloc(sizeof(*uval), GFP_KERNEL);
- if (!uval)
- return -ENOMEM;
- list_for_each_entry(slave, &master->slaves, list) {
- master->val = old_val;
- uval->id = slave->slave.id;
- slave_get_val(slave, uval);
- master->val = ucontrol->value.integer.value[0];
- slave_put_val(slave, uval);
- }
- kfree(uval);
- if (master->hook && !err)
- master->hook(master->hook_private_data, master->val);
- return 1;
-}
-
-static void master_free(struct snd_kcontrol *kcontrol)
-{
- struct link_master *master = snd_kcontrol_chip(kcontrol);
- struct link_slave *slave, *n;
-
- /* free all slave links and retore the original slave kctls */
- list_for_each_entry_safe(slave, n, &master->slaves, list) {
- struct snd_kcontrol *sctl = slave->kctl;
- struct list_head olist = sctl->list;
- memcpy(sctl, &slave->slave, sizeof(*sctl));
- memcpy(sctl->vd, slave->slave.vd,
- sctl->count * sizeof(*sctl->vd));
- sctl->list = olist; /* keep the current linked-list */
- kfree(slave);
- }
- kfree(master);
-}
-
-
-/**
- * snd_ctl_make_virtual_master - Create a virtual master control
- * @name: name string of the control element to create
- * @tlv: optional TLV int array for dB information
- *
- * Creates a virtual matster control with the given name string.
- * Returns the created control element, or NULL for errors (ENOMEM).
- *
- * After creating a vmaster element, you can add the slave controls
- * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
- *
- * The optional argument @tlv can be used to specify the TLV information
- * for dB scale of the master control. It should be a single element
- * with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or
- * #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB.
- */
-struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
- const unsigned int *tlv)
-{
- struct link_master *master;
- struct snd_kcontrol *kctl;
- struct snd_kcontrol_new knew;
-
- memset(&knew, 0, sizeof(knew));
- knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- knew.name = name;
- knew.info = master_info;
-
- master = kzalloc(sizeof(*master), GFP_KERNEL);
- if (!master)
- return NULL;
- INIT_LIST_HEAD(&master->slaves);
-
- kctl = snd_ctl_new1(&knew, master);
- if (!kctl) {
- kfree(master);
- return NULL;
- }
- /* override some callbacks */
- kctl->info = master_info;
- kctl->get = master_get;
- kctl->put = master_put;
- kctl->private_free = master_free;
-
- /* additional (constant) TLV read */
- if (tlv &&
- (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE ||
- tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX ||
- tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) {
- kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
- memcpy(master->tlv, tlv, sizeof(master->tlv));
- kctl->tlv.p = master->tlv;
- }
-
- return kctl;
-}
-EXPORT_SYMBOL(snd_ctl_make_virtual_master);
-
-/**
- * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
- * @kcontrol: vmaster kctl element
- * @hook: the hook function
- * @private_data: the private_data pointer to be saved
- *
- * Adds the given hook to the vmaster control element so that it's called
- * at each time when the value is changed.
- */
-int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
- void (*hook)(void *private_data, int),
- void *private_data)
-{
- struct link_master *master = snd_kcontrol_chip(kcontrol);
- master->hook = hook;
- master->hook_private_data = private_data;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook);
-
-/**
- * snd_ctl_sync_vmaster_hook - Sync the vmaster hook
- * @kcontrol: vmaster kctl element
- *
- * Call the hook function to synchronize with the current value of the given
- * vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't
- * exist.
- */
-void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol)
-{
- struct link_master *master;
- if (!kcontrol)
- return;
- master = snd_kcontrol_chip(kcontrol);
- if (master->hook)
- master->hook(master->hook_private_data, master->val);
-}
-EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook);