0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/time.h>
0023 #include <sound/core.h>
0024 #include <sound/pcm.h>
0025 #include <sound/pcm_params.h>
0026 #include "pcm_plugin.h"
0027
0028 #define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
0029 #define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count)
0030 #define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
0031 #define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count)
0032
0033
0034
0035
0036
0037 static snd_pcm_sframes_t io_playback_transfer(struct snd_pcm_plugin *plugin,
0038 const struct snd_pcm_plugin_channel *src_channels,
0039 struct snd_pcm_plugin_channel *dst_channels,
0040 snd_pcm_uframes_t frames)
0041 {
0042 if (snd_BUG_ON(!plugin))
0043 return -ENXIO;
0044 if (snd_BUG_ON(!src_channels))
0045 return -ENXIO;
0046 if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
0047 return pcm_write(plugin->plug, src_channels->area.addr, frames);
0048 } else {
0049 int channel, channels = plugin->dst_format.channels;
0050 void **bufs = (void**)plugin->extra_data;
0051 if (snd_BUG_ON(!bufs))
0052 return -ENXIO;
0053 for (channel = 0; channel < channels; channel++) {
0054 if (src_channels[channel].enabled)
0055 bufs[channel] = src_channels[channel].area.addr;
0056 else
0057 bufs[channel] = NULL;
0058 }
0059 return pcm_writev(plugin->plug, bufs, frames);
0060 }
0061 }
0062
0063 static snd_pcm_sframes_t io_capture_transfer(struct snd_pcm_plugin *plugin,
0064 const struct snd_pcm_plugin_channel *src_channels,
0065 struct snd_pcm_plugin_channel *dst_channels,
0066 snd_pcm_uframes_t frames)
0067 {
0068 if (snd_BUG_ON(!plugin))
0069 return -ENXIO;
0070 if (snd_BUG_ON(!dst_channels))
0071 return -ENXIO;
0072 if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
0073 return pcm_read(plugin->plug, dst_channels->area.addr, frames);
0074 } else {
0075 int channel, channels = plugin->dst_format.channels;
0076 void **bufs = (void**)plugin->extra_data;
0077 if (snd_BUG_ON(!bufs))
0078 return -ENXIO;
0079 for (channel = 0; channel < channels; channel++) {
0080 if (dst_channels[channel].enabled)
0081 bufs[channel] = dst_channels[channel].area.addr;
0082 else
0083 bufs[channel] = NULL;
0084 }
0085 return pcm_readv(plugin->plug, bufs, frames);
0086 }
0087 return 0;
0088 }
0089
0090 static snd_pcm_sframes_t io_src_channels(struct snd_pcm_plugin *plugin,
0091 snd_pcm_uframes_t frames,
0092 struct snd_pcm_plugin_channel **channels)
0093 {
0094 int err;
0095 unsigned int channel;
0096 struct snd_pcm_plugin_channel *v;
0097 err = snd_pcm_plugin_client_channels(plugin, frames, &v);
0098 if (err < 0)
0099 return err;
0100 *channels = v;
0101 if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
0102 for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v)
0103 v->wanted = 1;
0104 }
0105 return frames;
0106 }
0107
0108 int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug,
0109 struct snd_pcm_hw_params *params,
0110 struct snd_pcm_plugin **r_plugin)
0111 {
0112 int err;
0113 struct snd_pcm_plugin_format format;
0114 struct snd_pcm_plugin *plugin;
0115
0116 if (snd_BUG_ON(!r_plugin))
0117 return -ENXIO;
0118 *r_plugin = NULL;
0119 if (snd_BUG_ON(!plug || !params))
0120 return -ENXIO;
0121 format.format = params_format(params);
0122 format.rate = params_rate(params);
0123 format.channels = params_channels(params);
0124 err = snd_pcm_plugin_build(plug, "I/O io",
0125 &format, &format,
0126 sizeof(void *) * format.channels,
0127 &plugin);
0128 if (err < 0)
0129 return err;
0130 plugin->access = params_access(params);
0131 if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) {
0132 plugin->transfer = io_playback_transfer;
0133 if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED)
0134 plugin->client_channels = io_src_channels;
0135 } else {
0136 plugin->transfer = io_capture_transfer;
0137 }
0138
0139 *r_plugin = plugin;
0140 return 0;
0141 }