diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-04-28 09:13:41 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-06-22 15:33:13 -0400 |
commit | 0df63e44c3e315ec0fe427ae62558231864108bd (patch) | |
tree | 3cff6f5d5fdb7ad047a61c591d891e3ca1bc669e | |
parent | f001c3acf64b8ca18fe40af592629abb261b321e (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>
-rw-r--r-- | include/sound/asound.h | 2 | ||||
-rw-r--r-- | include/sound/pcm.h | 5 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 17 | ||||
-rw-r--r-- | sound/core/pcm.c | 25 | ||||
-rw-r--r-- | sound/core/pcm_compat.c | 4 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 8 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 81 | ||||
-rw-r--r-- | sound/usb/usx2y/usx2yhwdeppcm.c | 2 |
8 files changed, 99 insertions, 45 deletions
diff --git a/include/sound/asound.h b/include/sound/asound.h index 9cc021c7ee1..41885f48ad9 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h | |||
@@ -137,7 +137,7 @@ enum { | |||
137 | * * | 137 | * * |
138 | *****************************************************************************/ | 138 | *****************************************************************************/ |
139 | 139 | ||
140 | #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7) | 140 | #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 8) |
141 | 141 | ||
142 | typedef unsigned long snd_pcm_uframes_t; | 142 | typedef unsigned long snd_pcm_uframes_t; |
143 | typedef signed long snd_pcm_sframes_t; | 143 | typedef signed long snd_pcm_sframes_t; |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 998bacefc8f..cebf0310a8d 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -368,7 +368,8 @@ struct snd_pcm_substream { | |||
368 | struct snd_pcm_group *group; /* pointer to current group */ | 368 | struct snd_pcm_group *group; /* pointer to current group */ |
369 | /* -- assigned files -- */ | 369 | /* -- assigned files -- */ |
370 | void *file; | 370 | void *file; |
371 | struct file *ffile; | 371 | int ref_count; |
372 | unsigned int f_flags; | ||
372 | void (*pcm_release)(struct snd_pcm_substream *); | 373 | void (*pcm_release)(struct snd_pcm_substream *); |
373 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 374 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
374 | /* -- OSS things -- */ | 375 | /* -- OSS things -- */ |
@@ -387,7 +388,7 @@ struct snd_pcm_substream { | |||
387 | unsigned int hw_opened: 1; | 388 | unsigned int hw_opened: 1; |
388 | }; | 389 | }; |
389 | 390 | ||
390 | #define SUBSTREAM_BUSY(substream) ((substream)->file != NULL) | 391 | #define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0) |
391 | 392 | ||
392 | 393 | ||
393 | struct snd_pcm_str { | 394 | struct snd_pcm_str { |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index d8b7416ee00..9803a6ce3d4 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -1331,7 +1331,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
1331 | if (runtime->oss.period_ptr == 0 || | 1331 | if (runtime->oss.period_ptr == 0 || |
1332 | runtime->oss.period_ptr == runtime->oss.buffer_used) | 1332 | runtime->oss.period_ptr == runtime->oss.buffer_used) |
1333 | runtime->oss.buffer_used = 0; | 1333 | runtime->oss.buffer_used = 0; |
1334 | else if ((substream->ffile->f_flags & O_NONBLOCK) != 0) | 1334 | else if ((substream->f_flags & O_NONBLOCK) != 0) |
1335 | return xfer > 0 ? xfer : -EAGAIN; | 1335 | return xfer > 0 ? xfer : -EAGAIN; |
1336 | } | 1336 | } |
1337 | } else { | 1337 | } else { |
@@ -1344,7 +1344,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
1344 | buf += tmp; | 1344 | buf += tmp; |
1345 | bytes -= tmp; | 1345 | bytes -= tmp; |
1346 | xfer += tmp; | 1346 | xfer += tmp; |
1347 | if ((substream->ffile->f_flags & O_NONBLOCK) != 0 && | 1347 | if ((substream->f_flags & O_NONBLOCK) != 0 && |
1348 | tmp != runtime->oss.period_bytes) | 1348 | tmp != runtime->oss.period_bytes) |
1349 | break; | 1349 | break; |
1350 | } | 1350 | } |
@@ -1582,10 +1582,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1582 | * finish sync: drain the buffer | 1582 | * finish sync: drain the buffer |
1583 | */ | 1583 | */ |
1584 | __direct: | 1584 | __direct: |
1585 | saved_f_flags = substream->ffile->f_flags; | 1585 | saved_f_flags = substream->f_flags; |
1586 | substream->ffile->f_flags &= ~O_NONBLOCK; | 1586 | substream->f_flags &= ~O_NONBLOCK; |
1587 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); | 1587 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); |
1588 | substream->ffile->f_flags = saved_f_flags; | 1588 | substream->f_flags = saved_f_flags; |
1589 | if (err < 0) | 1589 | if (err < 0) |
1590 | return err; | 1590 | return err; |
1591 | runtime->oss.prepare = 1; | 1591 | runtime->oss.prepare = 1; |
@@ -2164,9 +2164,9 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, | |||
2164 | substream->oss.oss = 1; | 2164 | substream->oss.oss = 1; |
2165 | substream->oss.setup = *setup; | 2165 | substream->oss.setup = *setup; |
2166 | if (setup->nonblock) | 2166 | if (setup->nonblock) |
2167 | substream->ffile->f_flags |= O_NONBLOCK; | 2167 | substream->f_flags |= O_NONBLOCK; |
2168 | else if (setup->block) | 2168 | else if (setup->block) |
2169 | substream->ffile->f_flags &= ~O_NONBLOCK; | 2169 | substream->f_flags &= ~O_NONBLOCK; |
2170 | runtime = substream->runtime; | 2170 | runtime = substream->runtime; |
2171 | runtime->oss.params = 1; | 2171 | runtime->oss.params = 1; |
2172 | runtime->oss.trigger = 1; | 2172 | runtime->oss.trigger = 1; |
@@ -2223,6 +2223,7 @@ static int snd_pcm_oss_open_file(struct file *file, | |||
2223 | (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) | 2223 | (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) |
2224 | f_mode = FMODE_WRITE; | 2224 | f_mode = FMODE_WRITE; |
2225 | 2225 | ||
2226 | file->f_flags &= ~O_APPEND; | ||
2226 | for (idx = 0; idx < 2; idx++) { | 2227 | for (idx = 0; idx < 2; idx++) { |
2227 | if (setup[idx].disable) | 2228 | if (setup[idx].disable) |
2228 | continue; | 2229 | continue; |
@@ -2540,6 +2541,7 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun | |||
2540 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; | 2541 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; |
2541 | if (substream == NULL) | 2542 | if (substream == NULL) |
2542 | return -ENXIO; | 2543 | return -ENXIO; |
2544 | substream->f_flags = file->f_flags & O_NONBLOCK; | ||
2543 | #ifndef OSS_DEBUG | 2545 | #ifndef OSS_DEBUG |
2544 | return snd_pcm_oss_read1(substream, buf, count); | 2546 | return snd_pcm_oss_read1(substream, buf, count); |
2545 | #else | 2547 | #else |
@@ -2561,6 +2563,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size | |||
2561 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; | 2563 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; |
2562 | if (substream == NULL) | 2564 | if (substream == NULL) |
2563 | return -ENXIO; | 2565 | return -ENXIO; |
2566 | substream->f_flags = file->f_flags & O_NONBLOCK; | ||
2564 | result = snd_pcm_oss_write1(substream, buf, count); | 2567 | result = snd_pcm_oss_write1(substream, buf, count); |
2565 | #ifdef OSS_DEBUG | 2568 | #ifdef OSS_DEBUG |
2566 | printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); | 2569 | printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 4f5204175d3..8136be2e606 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -829,6 +829,26 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
829 | return -EINVAL; | 829 | return -EINVAL; |
830 | } | 830 | } |
831 | 831 | ||
832 | if (file->f_flags & O_APPEND) { | ||
833 | if (prefer_subdevice < 0) { | ||
834 | if (pstr->substream_count > 1) | ||
835 | return -EINVAL; /* must be unique */ | ||
836 | substream = pstr->substream; | ||
837 | } else { | ||
838 | for (substream = pstr->substream; substream; | ||
839 | substream = substream->next) | ||
840 | if (substream->number == prefer_subdevice) | ||
841 | break; | ||
842 | } | ||
843 | if (! substream) | ||
844 | return -ENODEV; | ||
845 | if (! SUBSTREAM_BUSY(substream)) | ||
846 | return -EBADFD; | ||
847 | substream->ref_count++; | ||
848 | *rsubstream = substream; | ||
849 | return 0; | ||
850 | } | ||
851 | |||
832 | if (prefer_subdevice >= 0) { | 852 | if (prefer_subdevice >= 0) { |
833 | for (substream = pstr->substream; substream; substream = substream->next) | 853 | for (substream = pstr->substream; substream; substream = substream->next) |
834 | if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) | 854 | if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) |
@@ -873,7 +893,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
873 | 893 | ||
874 | substream->runtime = runtime; | 894 | substream->runtime = runtime; |
875 | substream->private_data = pcm->private_data; | 895 | substream->private_data = pcm->private_data; |
876 | substream->ffile = file; | 896 | substream->ref_count = 1; |
897 | substream->f_flags = file->f_flags; | ||
877 | pstr->substream_opened++; | 898 | pstr->substream_opened++; |
878 | *rsubstream = substream; | 899 | *rsubstream = substream; |
879 | return 0; | 900 | return 0; |
@@ -882,7 +903,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
882 | void snd_pcm_detach_substream(struct snd_pcm_substream *substream) | 903 | void snd_pcm_detach_substream(struct snd_pcm_substream *substream) |
883 | { | 904 | { |
884 | struct snd_pcm_runtime *runtime; | 905 | struct snd_pcm_runtime *runtime; |
885 | substream->file = NULL; | 906 | |
886 | runtime = substream->runtime; | 907 | runtime = substream->runtime; |
887 | snd_assert(runtime != NULL, return); | 908 | snd_assert(runtime != NULL, return); |
888 | if (runtime->private_free != NULL) | 909 | if (runtime->private_free != NULL) |
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index e5133033de5..2b8aab6fd6c 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c | |||
@@ -497,9 +497,9 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l | |||
497 | case SNDRV_PCM_IOCTL_LINK: | 497 | case SNDRV_PCM_IOCTL_LINK: |
498 | case SNDRV_PCM_IOCTL_UNLINK: | 498 | case SNDRV_PCM_IOCTL_UNLINK: |
499 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 499 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
500 | return snd_pcm_playback_ioctl1(substream, cmd, argp); | 500 | return snd_pcm_playback_ioctl1(file, substream, cmd, argp); |
501 | else | 501 | else |
502 | return snd_pcm_capture_ioctl1(substream, cmd, argp); | 502 | return snd_pcm_capture_ioctl1(file, substream, cmd, argp); |
503 | case SNDRV_PCM_IOCTL_HW_REFINE32: | 503 | case SNDRV_PCM_IOCTL_HW_REFINE32: |
504 | return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); | 504 | return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); |
505 | case SNDRV_PCM_IOCTL_HW_PARAMS32: | 505 | case SNDRV_PCM_IOCTL_HW_PARAMS32: |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index a21aa0050e4..0bb142a2853 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1782,7 +1782,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v | |||
1782 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 1782 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
1783 | return -EBADFD; | 1783 | return -EBADFD; |
1784 | 1784 | ||
1785 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 1785 | nonblock = !!(substream->f_flags & O_NONBLOCK); |
1786 | 1786 | ||
1787 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && | 1787 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && |
1788 | runtime->channels > 1) | 1788 | runtime->channels > 1) |
@@ -1847,7 +1847,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, | |||
1847 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 1847 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
1848 | return -EBADFD; | 1848 | return -EBADFD; |
1849 | 1849 | ||
1850 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 1850 | nonblock = !!(substream->f_flags & O_NONBLOCK); |
1851 | 1851 | ||
1852 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) | 1852 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) |
1853 | return -EINVAL; | 1853 | return -EINVAL; |
@@ -2059,7 +2059,7 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u | |||
2059 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 2059 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2060 | return -EBADFD; | 2060 | return -EBADFD; |
2061 | 2061 | ||
2062 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 2062 | nonblock = !!(substream->f_flags & O_NONBLOCK); |
2063 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) | 2063 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) |
2064 | return -EINVAL; | 2064 | return -EINVAL; |
2065 | return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); | 2065 | return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); |
@@ -2118,7 +2118,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, | |||
2118 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 2118 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2119 | return -EBADFD; | 2119 | return -EBADFD; |
2120 | 2120 | ||
2121 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 2121 | nonblock = !!(substream->f_flags & O_NONBLOCK); |
2122 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) | 2122 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) |
2123 | return -EINVAL; | 2123 | return -EINVAL; |
2124 | return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); | 2124 | return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); |
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 | */ |
1287 | static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int state) | 1287 | /* we use the second argument for updating f_flags */ |
1288 | static 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 | */ |
1325 | static int snd_pcm_prepare(struct snd_pcm_substream *substream) | 1329 | static 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 | ||
1341 | static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) | 1353 | static 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 | ||
2016 | void snd_pcm_release_substream(struct snd_pcm_substream *substream) | 2028 | void 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 | ||
2509 | static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, | 2533 | static 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 | ||
2576 | static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, | 2601 | static 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 | ||
2655 | static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, | 2681 | static 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 | ||
2734 | static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, | 2761 | static 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 | ||
2747 | static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, | 2775 | static 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 | ||
2760 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, | 2789 | int 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; |
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index fe67a92e2a1..88b72b52590 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c | |||
@@ -632,7 +632,7 @@ static int usX2Y_pcms_lock_check(struct snd_card *card) | |||
632 | for (s = 0; s < 2; ++s) { | 632 | for (s = 0; s < 2; ++s) { |
633 | struct snd_pcm_substream *substream; | 633 | struct snd_pcm_substream *substream; |
634 | substream = pcm->streams[s].substream; | 634 | substream = pcm->streams[s].substream; |
635 | if (substream && substream->ffile != NULL) | 635 | if (SUBSTREAM_BUSY(substream)) |
636 | err = -EBUSY; | 636 | err = -EBUSY; |
637 | } | 637 | } |
638 | } | 638 | } |