aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/oss/pcm_oss.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/oss/pcm_oss.c')
-rw-r--r--sound/core/oss/pcm_oss.c151
1 files changed, 44 insertions, 107 deletions
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 54be0bba6bd2..c056cbfe5519 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1671,6 +1671,18 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm,
1671 return NULL; 1671 return NULL;
1672} 1672}
1673 1673
1674static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
1675{
1676 struct snd_pcm_runtime *runtime;
1677 runtime = substream->runtime;
1678 vfree(runtime->oss.buffer);
1679 runtime->oss.buffer = NULL;
1680#ifdef CONFIG_SND_PCM_OSS_PLUGINS
1681 snd_pcm_oss_plugin_clear(substream);
1682#endif
1683 substream->oss.oss = 0;
1684}
1685
1674static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, 1686static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
1675 struct snd_pcm_oss_setup *setup, 1687 struct snd_pcm_oss_setup *setup,
1676 int minor) 1688 int minor)
@@ -1679,6 +1691,10 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
1679 1691
1680 substream->oss.oss = 1; 1692 substream->oss.oss = 1;
1681 substream->oss.setup = setup; 1693 substream->oss.setup = setup;
1694 if (setup->nonblock)
1695 substream->ffile->f_flags |= O_NONBLOCK;
1696 else
1697 substream->ffile->f_flags &= ~O_NONBLOCK;
1682 runtime = substream->runtime; 1698 runtime = substream->runtime;
1683 runtime->oss.params = 1; 1699 runtime->oss.params = 1;
1684 runtime->oss.trigger = 1; 1700 runtime->oss.trigger = 1;
@@ -1697,18 +1713,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
1697 runtime->oss.fragshift = 0; 1713 runtime->oss.fragshift = 0;
1698 runtime->oss.maxfrags = 0; 1714 runtime->oss.maxfrags = 0;
1699 runtime->oss.subdivision = 0; 1715 runtime->oss.subdivision = 0;
1700} 1716 substream->pcm_release = snd_pcm_oss_release_substream;
1701
1702static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
1703{
1704 struct snd_pcm_runtime *runtime;
1705 runtime = substream->runtime;
1706 vfree(runtime->oss.buffer);
1707#ifdef CONFIG_SND_PCM_OSS_PLUGINS
1708 snd_pcm_oss_plugin_clear(substream);
1709#endif
1710 substream->oss.file = NULL;
1711 substream->oss.oss = 0;
1712} 1717}
1713 1718
1714static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) 1719static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
@@ -1717,23 +1722,8 @@ static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
1717 snd_assert(pcm_oss_file != NULL, return -ENXIO); 1722 snd_assert(pcm_oss_file != NULL, return -ENXIO);
1718 for (cidx = 0; cidx < 2; ++cidx) { 1723 for (cidx = 0; cidx < 2; ++cidx) {
1719 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; 1724 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
1720 struct snd_pcm_runtime *runtime; 1725 if (substream)
1721 if (substream == NULL) 1726 snd_pcm_release_substream(substream);
1722 continue;
1723 runtime = substream->runtime;
1724
1725 snd_pcm_stream_lock_irq(substream);
1726 if (snd_pcm_running(substream))
1727 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1728 snd_pcm_stream_unlock_irq(substream);
1729 if (substream->ffile != NULL) {
1730 if (substream->ops->hw_free != NULL)
1731 substream->ops->hw_free(substream);
1732 substream->ops->close(substream);
1733 substream->ffile = NULL;
1734 }
1735 snd_pcm_oss_release_substream(substream);
1736 snd_pcm_release_substream(substream);
1737 } 1727 }
1738 kfree(pcm_oss_file); 1728 kfree(pcm_oss_file);
1739 return 0; 1729 return 0;
@@ -1743,12 +1733,11 @@ static int snd_pcm_oss_open_file(struct file *file,
1743 struct snd_pcm *pcm, 1733 struct snd_pcm *pcm,
1744 struct snd_pcm_oss_file **rpcm_oss_file, 1734 struct snd_pcm_oss_file **rpcm_oss_file,
1745 int minor, 1735 int minor,
1746 struct snd_pcm_oss_setup *psetup, 1736 struct snd_pcm_oss_setup **setup)
1747 struct snd_pcm_oss_setup *csetup)
1748{ 1737{
1749 int err = 0; 1738 int idx, err;
1750 struct snd_pcm_oss_file *pcm_oss_file; 1739 struct snd_pcm_oss_file *pcm_oss_file;
1751 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 1740 struct snd_pcm_substream *substream;
1752 unsigned int f_mode = file->f_mode; 1741 unsigned int f_mode = file->f_mode;
1753 1742
1754 snd_assert(rpcm_oss_file != NULL, return -EINVAL); 1743 snd_assert(rpcm_oss_file != NULL, return -EINVAL);
@@ -1761,73 +1750,31 @@ static int snd_pcm_oss_open_file(struct file *file,
1761 if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) && 1750 if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
1762 (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) 1751 (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
1763 f_mode = FMODE_WRITE; 1752 f_mode = FMODE_WRITE;
1764 if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) { 1753
1765 if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1754 for (idx = 0; idx < 2; idx++) {
1766 &psubstream)) < 0) { 1755 if (! setup[idx] || setup[idx]->disable)
1756 continue;
1757 if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
1758 if (! (f_mode & FMODE_WRITE))
1759 continue;
1760 } else {
1761 if (! (f_mode & FMODE_READ))
1762 continue;
1763 }
1764 err = snd_pcm_open_substream(pcm, idx, file, &substream);
1765 if (err < 0) {
1767 snd_pcm_oss_release_file(pcm_oss_file); 1766 snd_pcm_oss_release_file(pcm_oss_file);
1768 return err; 1767 return err;
1769 } 1768 }
1770 pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream; 1769
1771 } 1770 pcm_oss_file->streams[idx] = substream;
1772 if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) { 1771 snd_pcm_oss_init_substream(substream, setup[idx], minor);
1773 if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE,
1774 &csubstream)) < 0) {
1775 if (!(f_mode & FMODE_WRITE) || err != -ENODEV) {
1776 snd_pcm_oss_release_file(pcm_oss_file);
1777 return err;
1778 } else {
1779 csubstream = NULL;
1780 }
1781 }
1782 pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;
1783 } 1772 }
1784 1773
1785 if (psubstream == NULL && csubstream == NULL) { 1774 if (! pcm_oss_file->streams[0] && pcm_oss_file->streams[1]) {
1786 snd_pcm_oss_release_file(pcm_oss_file); 1775 snd_pcm_oss_release_file(pcm_oss_file);
1787 return -EINVAL; 1776 return -EINVAL;
1788 } 1777 }
1789 if (psubstream != NULL) {
1790 psubstream->oss.file = pcm_oss_file;
1791 err = snd_pcm_hw_constraints_init(psubstream);
1792 if (err < 0) {
1793 snd_printd("snd_pcm_hw_constraint_init failed\n");
1794 snd_pcm_oss_release_file(pcm_oss_file);
1795 return err;
1796 }
1797 if ((err = psubstream->ops->open(psubstream)) < 0) {
1798 snd_pcm_oss_release_file(pcm_oss_file);
1799 return err;
1800 }
1801 psubstream->ffile = file;
1802 err = snd_pcm_hw_constraints_complete(psubstream);
1803 if (err < 0) {
1804 snd_printd("snd_pcm_hw_constraint_complete failed\n");
1805 snd_pcm_oss_release_file(pcm_oss_file);
1806 return err;
1807 }
1808 snd_pcm_oss_init_substream(psubstream, psetup, minor);
1809 }
1810 if (csubstream != NULL) {
1811 csubstream->oss.file = pcm_oss_file;
1812 err = snd_pcm_hw_constraints_init(csubstream);
1813 if (err < 0) {
1814 snd_printd("snd_pcm_hw_constraint_init failed\n");
1815 snd_pcm_oss_release_file(pcm_oss_file);
1816 return err;
1817 }
1818 if ((err = csubstream->ops->open(csubstream)) < 0) {
1819 snd_pcm_oss_release_file(pcm_oss_file);
1820 return err;
1821 }
1822 csubstream->ffile = file;
1823 err = snd_pcm_hw_constraints_complete(csubstream);
1824 if (err < 0) {
1825 snd_printd("snd_pcm_hw_constraint_complete failed\n");
1826 snd_pcm_oss_release_file(pcm_oss_file);
1827 return err;
1828 }
1829 snd_pcm_oss_init_substream(csubstream, csetup, minor);
1830 }
1831 1778
1832 file->private_data = pcm_oss_file; 1779 file->private_data = pcm_oss_file;
1833 *rpcm_oss_file = pcm_oss_file; 1780 *rpcm_oss_file = pcm_oss_file;
@@ -1852,7 +1799,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1852 char task_name[32]; 1799 char task_name[32];
1853 struct snd_pcm *pcm; 1800 struct snd_pcm *pcm;
1854 struct snd_pcm_oss_file *pcm_oss_file; 1801 struct snd_pcm_oss_file *pcm_oss_file;
1855 struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL; 1802 struct snd_pcm_oss_setup *setup[2];
1856 int nonblock; 1803 int nonblock;
1857 wait_queue_t wait; 1804 wait_queue_t wait;
1858 1805
@@ -1873,23 +1820,13 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1873 err = -EFAULT; 1820 err = -EFAULT;
1874 goto __error; 1821 goto __error;
1875 } 1822 }
1823 memset(setup, 0, sizeof(*setup));
1876 if (file->f_mode & FMODE_WRITE) 1824 if (file->f_mode & FMODE_WRITE)
1877 psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name); 1825 setup[0] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
1878 if (file->f_mode & FMODE_READ) 1826 if (file->f_mode & FMODE_READ)
1879 csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name); 1827 setup[1] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
1880 1828
1881 nonblock = !!(file->f_flags & O_NONBLOCK); 1829 nonblock = !!(file->f_flags & O_NONBLOCK);
1882 if (psetup && !psetup->disable) {
1883 if (psetup->nonblock)
1884 nonblock = 1;
1885 else if (psetup->block)
1886 nonblock = 0;
1887 } else if (csetup && !csetup->disable) {
1888 if (csetup->nonblock)
1889 nonblock = 1;
1890 else if (csetup->block)
1891 nonblock = 0;
1892 }
1893 if (!nonblock) 1830 if (!nonblock)
1894 nonblock = nonblock_open; 1831 nonblock = nonblock_open;
1895 1832
@@ -1898,7 +1835,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1898 mutex_lock(&pcm->open_mutex); 1835 mutex_lock(&pcm->open_mutex);
1899 while (1) { 1836 while (1) {
1900 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, 1837 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
1901 iminor(inode), psetup, csetup); 1838 iminor(inode), setup);
1902 if (err >= 0) 1839 if (err >= 0)
1903 break; 1840 break;
1904 if (err == -EAGAIN) { 1841 if (err == -EAGAIN) {