aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm_native.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-04-28 09:13:41 -0400
committerJaroslav Kysela <perex@suse.cz>2006-06-22 15:33:13 -0400
commit0df63e44c3e315ec0fe427ae62558231864108bd (patch)
tree3cff6f5d5fdb7ad047a61c591d891e3ca1bc669e /sound/core/pcm_native.c
parentf001c3acf64b8ca18fe40af592629abb261b321e (diff)
[ALSA] Add O_APPEND flag support to PCM
Added O_APPEND flag support to PCM to enable shared substreams among multiple processes. This mechanism is used by dmix and dsnoop plugins. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/pcm_native.c')
-rw-r--r--sound/core/pcm_native.c81
1 files changed, 55 insertions, 26 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 7b5729c4b21..36d6765618a 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1284,13 +1284,16 @@ static int snd_pcm_reset(struct snd_pcm_substream *substream)
1284/* 1284/*
1285 * prepare ioctl 1285 * prepare ioctl
1286 */ 1286 */
1287static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int state) 1287/* we use the second argument for updating f_flags */
1288static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
1289 int f_flags)
1288{ 1290{
1289 struct snd_pcm_runtime *runtime = substream->runtime; 1291 struct snd_pcm_runtime *runtime = substream->runtime;
1290 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 1292 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
1291 return -EBADFD; 1293 return -EBADFD;
1292 if (snd_pcm_running(substream)) 1294 if (snd_pcm_running(substream))
1293 return -EBUSY; 1295 return -EBUSY;
1296 substream->f_flags = f_flags;
1294 return 0; 1297 return 0;
1295} 1298}
1296 1299
@@ -1319,17 +1322,26 @@ static struct action_ops snd_pcm_action_prepare = {
1319/** 1322/**
1320 * snd_pcm_prepare 1323 * snd_pcm_prepare
1321 * @substream: the PCM substream instance 1324 * @substream: the PCM substream instance
1325 * @file: file to refer f_flags
1322 * 1326 *
1323 * Prepare the PCM substream to be triggerable. 1327 * Prepare the PCM substream to be triggerable.
1324 */ 1328 */
1325static int snd_pcm_prepare(struct snd_pcm_substream *substream) 1329static int snd_pcm_prepare(struct snd_pcm_substream *substream,
1330 struct file *file)
1326{ 1331{
1327 int res; 1332 int res;
1328 struct snd_card *card = substream->pcm->card; 1333 struct snd_card *card = substream->pcm->card;
1334 int f_flags;
1335
1336 if (file)
1337 f_flags = file->f_flags;
1338 else
1339 f_flags = substream->f_flags;
1329 1340
1330 snd_power_lock(card); 1341 snd_power_lock(card);
1331 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) 1342 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
1332 res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0); 1343 res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
1344 substream, f_flags);
1333 snd_power_unlock(card); 1345 snd_power_unlock(card);
1334 return res; 1346 return res;
1335} 1347}
@@ -1340,7 +1352,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream)
1340 1352
1341static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) 1353static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
1342{ 1354{
1343 if (substream->ffile->f_flags & O_NONBLOCK) 1355 if (substream->f_flags & O_NONBLOCK)
1344 return -EAGAIN; 1356 return -EAGAIN;
1345 substream->runtime->trigger_master = substream; 1357 substream->runtime->trigger_master = substream;
1346 return 0; 1358 return 0;
@@ -2015,6 +2027,10 @@ static void pcm_release_private(struct snd_pcm_substream *substream)
2015 2027
2016void snd_pcm_release_substream(struct snd_pcm_substream *substream) 2028void snd_pcm_release_substream(struct snd_pcm_substream *substream)
2017{ 2029{
2030 substream->ref_count--;
2031 if (substream->ref_count > 0)
2032 return;
2033
2018 snd_pcm_drop(substream); 2034 snd_pcm_drop(substream);
2019 if (substream->hw_opened) { 2035 if (substream->hw_opened) {
2020 if (substream->ops->hw_free != NULL) 2036 if (substream->ops->hw_free != NULL)
@@ -2041,6 +2057,11 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
2041 err = snd_pcm_attach_substream(pcm, stream, file, &substream); 2057 err = snd_pcm_attach_substream(pcm, stream, file, &substream);
2042 if (err < 0) 2058 if (err < 0)
2043 return err; 2059 return err;
2060 if (substream->ref_count > 1) {
2061 *rsubstream = substream;
2062 return 0;
2063 }
2064
2044 substream->no_mmap_ctrl = 0; 2065 substream->no_mmap_ctrl = 0;
2045 err = snd_pcm_hw_constraints_init(substream); 2066 err = snd_pcm_hw_constraints_init(substream);
2046 if (err < 0) { 2067 if (err < 0) {
@@ -2086,17 +2107,20 @@ static int snd_pcm_open_file(struct file *file,
2086 if (err < 0) 2107 if (err < 0)
2087 return err; 2108 return err;
2088 2109
2089 pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); 2110 if (substream->ref_count > 1)
2090 if (pcm_file == NULL) { 2111 pcm_file = substream->file;
2091 snd_pcm_release_substream(substream); 2112 else {
2092 return -ENOMEM; 2113 pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
2114 if (pcm_file == NULL) {
2115 snd_pcm_release_substream(substream);
2116 return -ENOMEM;
2117 }
2118 str = substream->pstr;
2119 substream->file = pcm_file;
2120 substream->pcm_release = pcm_release_private;
2121 pcm_file->substream = substream;
2122 snd_pcm_add_file(str, pcm_file);
2093 } 2123 }
2094 str = substream->pstr;
2095 substream->file = pcm_file;
2096 substream->pcm_release = pcm_release_private;
2097 pcm_file->substream = substream;
2098 snd_pcm_add_file(str, pcm_file);
2099
2100 file->private_data = pcm_file; 2124 file->private_data = pcm_file;
2101 *rpcm_file = pcm_file; 2125 *rpcm_file = pcm_file;
2102 return 0; 2126 return 0;
@@ -2506,7 +2530,8 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
2506 return 0; 2530 return 0;
2507} 2531}
2508 2532
2509static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, 2533static int snd_pcm_common_ioctl1(struct file *file,
2534 struct snd_pcm_substream *substream,
2510 unsigned int cmd, void __user *arg) 2535 unsigned int cmd, void __user *arg)
2511{ 2536{
2512 snd_assert(substream != NULL, return -ENXIO); 2537 snd_assert(substream != NULL, return -ENXIO);
@@ -2531,7 +2556,7 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
2531 case SNDRV_PCM_IOCTL_CHANNEL_INFO: 2556 case SNDRV_PCM_IOCTL_CHANNEL_INFO:
2532 return snd_pcm_channel_info_user(substream, arg); 2557 return snd_pcm_channel_info_user(substream, arg);
2533 case SNDRV_PCM_IOCTL_PREPARE: 2558 case SNDRV_PCM_IOCTL_PREPARE:
2534 return snd_pcm_prepare(substream); 2559 return snd_pcm_prepare(substream, file);
2535 case SNDRV_PCM_IOCTL_RESET: 2560 case SNDRV_PCM_IOCTL_RESET:
2536 return snd_pcm_reset(substream); 2561 return snd_pcm_reset(substream);
2537 case SNDRV_PCM_IOCTL_START: 2562 case SNDRV_PCM_IOCTL_START:
@@ -2573,7 +2598,8 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
2573 return -ENOTTY; 2598 return -ENOTTY;
2574} 2599}
2575 2600
2576static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, 2601static int snd_pcm_playback_ioctl1(struct file *file,
2602 struct snd_pcm_substream *substream,
2577 unsigned int cmd, void __user *arg) 2603 unsigned int cmd, void __user *arg)
2578{ 2604{
2579 snd_assert(substream != NULL, return -ENXIO); 2605 snd_assert(substream != NULL, return -ENXIO);
@@ -2649,10 +2675,11 @@ static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
2649 return result < 0 ? result : 0; 2675 return result < 0 ? result : 0;
2650 } 2676 }
2651 } 2677 }
2652 return snd_pcm_common_ioctl1(substream, cmd, arg); 2678 return snd_pcm_common_ioctl1(file, substream, cmd, arg);
2653} 2679}
2654 2680
2655static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, 2681static int snd_pcm_capture_ioctl1(struct file *file,
2682 struct snd_pcm_substream *substream,
2656 unsigned int cmd, void __user *arg) 2683 unsigned int cmd, void __user *arg)
2657{ 2684{
2658 snd_assert(substream != NULL, return -ENXIO); 2685 snd_assert(substream != NULL, return -ENXIO);
@@ -2728,7 +2755,7 @@ static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
2728 return result < 0 ? result : 0; 2755 return result < 0 ? result : 0;
2729 } 2756 }
2730 } 2757 }
2731 return snd_pcm_common_ioctl1(substream, cmd, arg); 2758 return snd_pcm_common_ioctl1(file, substream, cmd, arg);
2732} 2759}
2733 2760
2734static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, 2761static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
@@ -2741,7 +2768,8 @@ static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
2741 if (((cmd >> 8) & 0xff) != 'A') 2768 if (((cmd >> 8) & 0xff) != 'A')
2742 return -ENOTTY; 2769 return -ENOTTY;
2743 2770
2744 return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); 2771 return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
2772 (void __user *)arg);
2745} 2773}
2746 2774
2747static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, 2775static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
@@ -2754,7 +2782,8 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
2754 if (((cmd >> 8) & 0xff) != 'A') 2782 if (((cmd >> 8) & 0xff) != 'A')
2755 return -ENOTTY; 2783 return -ENOTTY;
2756 2784
2757 return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); 2785 return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
2786 (void __user *)arg);
2758} 2787}
2759 2788
2760int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, 2789int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
@@ -2766,12 +2795,12 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
2766 fs = snd_enter_user(); 2795 fs = snd_enter_user();
2767 switch (substream->stream) { 2796 switch (substream->stream) {
2768 case SNDRV_PCM_STREAM_PLAYBACK: 2797 case SNDRV_PCM_STREAM_PLAYBACK:
2769 result = snd_pcm_playback_ioctl1(substream, 2798 result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
2770 cmd, (void __user *)arg); 2799 (void __user *)arg);
2771 break; 2800 break;
2772 case SNDRV_PCM_STREAM_CAPTURE: 2801 case SNDRV_PCM_STREAM_CAPTURE:
2773 result = snd_pcm_capture_ioctl1(substream, 2802 result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
2774 cmd, (void __user *)arg); 2803 (void __user *)arg);
2775 break; 2804 break;
2776 default: 2805 default:
2777 result = -EINVAL; 2806 result = -EINVAL;