diff options
| -rw-r--r-- | include/sound/pcm_oss.h | 2 | ||||
| -rw-r--r-- | sound/core/oss/pcm_oss.c | 133 |
2 files changed, 64 insertions, 71 deletions
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h index 1d522aaa66df..39df2baca18a 100644 --- a/include/sound/pcm_oss.h +++ b/include/sound/pcm_oss.h | |||
| @@ -69,7 +69,7 @@ struct snd_pcm_oss_file { | |||
| 69 | 69 | ||
| 70 | struct snd_pcm_oss_substream { | 70 | struct snd_pcm_oss_substream { |
| 71 | unsigned oss: 1; /* oss mode */ | 71 | unsigned oss: 1; /* oss mode */ |
| 72 | struct snd_pcm_oss_setup *setup; /* active setup */ | 72 | struct snd_pcm_oss_setup setup; /* active setup */ |
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | struct snd_pcm_oss_stream { | 75 | struct snd_pcm_oss_stream { |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index c056cbfe5519..91114c7aeff5 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
| @@ -208,9 +208,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, | |||
| 208 | oss_buffer_size = runtime->oss.mmap_bytes; | 208 | oss_buffer_size = runtime->oss.mmap_bytes; |
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | if (substream->oss.setup && | 211 | if (substream->oss.setup.period_size > 16) |
| 212 | substream->oss.setup->period_size > 16) | 212 | oss_period_size = substream->oss.setup.period_size; |
| 213 | oss_period_size = substream->oss.setup->period_size; | ||
| 214 | else if (runtime->oss.fragshift) { | 213 | else if (runtime->oss.fragshift) { |
| 215 | oss_period_size = 1 << runtime->oss.fragshift; | 214 | oss_period_size = 1 << runtime->oss.fragshift; |
| 216 | if (oss_period_size > oss_buffer_size / 2) | 215 | if (oss_period_size > oss_buffer_size / 2) |
| @@ -252,10 +251,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, | |||
| 252 | 251 | ||
| 253 | oss_periods = oss_buffer_size / oss_period_size; | 252 | oss_periods = oss_buffer_size / oss_period_size; |
| 254 | 253 | ||
| 255 | if (substream->oss.setup) { | 254 | if (substream->oss.setup.periods > 1) |
| 256 | if (substream->oss.setup->periods > 1) | 255 | oss_periods = substream->oss.setup.periods; |
| 257 | oss_periods = substream->oss.setup->periods; | ||
| 258 | } | ||
| 259 | 256 | ||
| 260 | s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); | 257 | s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); |
| 261 | if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) | 258 | if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) |
| @@ -341,12 +338,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
| 341 | goto failure; | 338 | goto failure; |
| 342 | } | 339 | } |
| 343 | 340 | ||
| 344 | if (atomic_read(&runtime->mmap_count)) { | 341 | if (atomic_read(&runtime->mmap_count)) |
| 345 | direct = 1; | 342 | direct = 1; |
| 346 | } else { | 343 | else |
| 347 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | 344 | direct = substream->oss.setup.direct; |
| 348 | direct = (setup != NULL && setup->direct); | ||
| 349 | } | ||
| 350 | 345 | ||
| 351 | _snd_pcm_hw_params_any(sparams); | 346 | _snd_pcm_hw_params_any(sparams); |
| 352 | _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); | 347 | _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); |
| @@ -482,7 +477,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
| 482 | 1 : runtime->period_size; | 477 | 1 : runtime->period_size; |
| 483 | sw_params->xfer_align = 1; | 478 | sw_params->xfer_align = 1; |
| 484 | if (atomic_read(&runtime->mmap_count) || | 479 | if (atomic_read(&runtime->mmap_count) || |
| 485 | (substream->oss.setup && substream->oss.setup->nosilence)) { | 480 | substream->oss.setup.nosilence) { |
| 486 | sw_params->silence_threshold = 0; | 481 | sw_params->silence_threshold = 0; |
| 487 | sw_params->silence_size = 0; | 482 | sw_params->silence_size = 0; |
| 488 | } else { | 483 | } else { |
| @@ -843,7 +838,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
| 843 | buf += tmp; | 838 | buf += tmp; |
| 844 | bytes -= tmp; | 839 | bytes -= tmp; |
| 845 | xfer += tmp; | 840 | xfer += tmp; |
| 846 | if ((substream->oss.setup != NULL && substream->oss.setup->partialfrag) || | 841 | if (substream->oss.setup.partialfrag || |
| 847 | runtime->oss.buffer_used == runtime->oss.period_bytes) { | 842 | runtime->oss.buffer_used == runtime->oss.period_bytes) { |
| 848 | tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, | 843 | tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, |
| 849 | runtime->oss.buffer_used - runtime->oss.period_ptr, 1); | 844 | runtime->oss.buffer_used - runtime->oss.period_ptr, 1); |
| @@ -1214,12 +1209,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) | |||
| 1214 | 1209 | ||
| 1215 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) | 1210 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) |
| 1216 | return err; | 1211 | return err; |
| 1217 | if (atomic_read(&substream->runtime->mmap_count)) { | 1212 | if (atomic_read(&substream->runtime->mmap_count)) |
| 1218 | direct = 1; | 1213 | direct = 1; |
| 1219 | } else { | 1214 | else |
| 1220 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | 1215 | direct = substream->oss.setup.direct; |
| 1221 | direct = (setup != NULL && setup->direct); | ||
| 1222 | } | ||
| 1223 | if (!direct) | 1216 | if (!direct) |
| 1224 | return AFMT_MU_LAW | AFMT_U8 | | 1217 | return AFMT_MU_LAW | AFMT_U8 | |
| 1225 | AFMT_S16_LE | AFMT_S16_BE | | 1218 | AFMT_S16_LE | AFMT_S16_BE | |
| @@ -1555,8 +1548,7 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream | |||
| 1555 | } else { | 1548 | } else { |
| 1556 | delay = snd_pcm_oss_bytes(substream, delay); | 1549 | delay = snd_pcm_oss_bytes(substream, delay); |
| 1557 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1550 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 1558 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | 1551 | if (substream->oss.setup.buggyptr) |
| 1559 | if (setup && setup->buggyptr) | ||
| 1560 | info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; | 1552 | info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; |
| 1561 | else | 1553 | else |
| 1562 | info.blocks = (delay + fixup) / runtime->oss.period_bytes; | 1554 | info.blocks = (delay + fixup) / runtime->oss.period_bytes; |
| @@ -1638,37 +1630,34 @@ static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int str | |||
| 1638 | return -EINVAL; | 1630 | return -EINVAL; |
| 1639 | } | 1631 | } |
| 1640 | 1632 | ||
| 1641 | static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, const char *task_name) | 1633 | static const char *strip_task_path(const char *path) |
| 1642 | { | 1634 | { |
| 1643 | const char *ptr, *ptrl; | 1635 | const char *ptr, *ptrl = NULL; |
| 1644 | struct snd_pcm_oss_setup *setup; | 1636 | for (ptr = path; *ptr; ptr++) { |
| 1645 | |||
| 1646 | mutex_lock(&pcm->streams[stream].oss.setup_mutex); | ||
| 1647 | for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { | ||
| 1648 | if (!strcmp(setup->task_name, task_name)) { | ||
| 1649 | mutex_unlock(&pcm->streams[stream].oss.setup_mutex); | ||
| 1650 | return setup; | ||
| 1651 | } | ||
| 1652 | } | ||
| 1653 | ptr = ptrl = task_name; | ||
| 1654 | while (*ptr) { | ||
| 1655 | if (*ptr == '/') | 1637 | if (*ptr == '/') |
| 1656 | ptrl = ptr + 1; | 1638 | ptrl = ptr + 1; |
| 1657 | ptr++; | ||
| 1658 | } | ||
| 1659 | if (ptrl == task_name) { | ||
| 1660 | goto __not_found; | ||
| 1661 | return NULL; | ||
| 1662 | } | 1639 | } |
| 1663 | for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { | 1640 | return ptrl; |
| 1664 | if (!strcmp(setup->task_name, ptrl)) { | 1641 | } |
| 1665 | mutex_unlock(&pcm->streams[stream].oss.setup_mutex); | 1642 | |
| 1666 | return setup; | 1643 | static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, |
| 1644 | const char *task_name, | ||
| 1645 | struct snd_pcm_oss_setup *rsetup) | ||
| 1646 | { | ||
| 1647 | struct snd_pcm_oss_setup *setup; | ||
| 1648 | |||
| 1649 | mutex_lock(&pcm->streams[stream].oss.setup_mutex); | ||
| 1650 | do { | ||
| 1651 | for (setup = pcm->streams[stream].oss.setup_list; setup; | ||
| 1652 | setup = setup->next) { | ||
| 1653 | if (!strcmp(setup->task_name, task_name)) | ||
| 1654 | goto out; | ||
| 1667 | } | 1655 | } |
| 1668 | } | 1656 | } while ((task_name = strip_task_path(task_name)) != NULL); |
| 1669 | __not_found: | 1657 | out: |
| 1658 | if (setup) | ||
| 1659 | *rsetup = *setup; | ||
| 1670 | mutex_unlock(&pcm->streams[stream].oss.setup_mutex); | 1660 | mutex_unlock(&pcm->streams[stream].oss.setup_mutex); |
| 1671 | return NULL; | ||
| 1672 | } | 1661 | } |
| 1673 | 1662 | ||
| 1674 | static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) | 1663 | static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) |
| @@ -1690,7 +1679,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, | |||
| 1690 | struct snd_pcm_runtime *runtime; | 1679 | struct snd_pcm_runtime *runtime; |
| 1691 | 1680 | ||
| 1692 | substream->oss.oss = 1; | 1681 | substream->oss.oss = 1; |
| 1693 | substream->oss.setup = setup; | 1682 | substream->oss.setup = *setup; |
| 1694 | if (setup->nonblock) | 1683 | if (setup->nonblock) |
| 1695 | substream->ffile->f_flags |= O_NONBLOCK; | 1684 | substream->ffile->f_flags |= O_NONBLOCK; |
| 1696 | else | 1685 | else |
| @@ -1733,7 +1722,7 @@ static int snd_pcm_oss_open_file(struct file *file, | |||
| 1733 | struct snd_pcm *pcm, | 1722 | struct snd_pcm *pcm, |
| 1734 | struct snd_pcm_oss_file **rpcm_oss_file, | 1723 | struct snd_pcm_oss_file **rpcm_oss_file, |
| 1735 | int minor, | 1724 | int minor, |
| 1736 | struct snd_pcm_oss_setup **setup) | 1725 | struct snd_pcm_oss_setup *setup) |
| 1737 | { | 1726 | { |
| 1738 | int idx, err; | 1727 | int idx, err; |
| 1739 | struct snd_pcm_oss_file *pcm_oss_file; | 1728 | struct snd_pcm_oss_file *pcm_oss_file; |
| @@ -1752,7 +1741,7 @@ static int snd_pcm_oss_open_file(struct file *file, | |||
| 1752 | f_mode = FMODE_WRITE; | 1741 | f_mode = FMODE_WRITE; |
| 1753 | 1742 | ||
| 1754 | for (idx = 0; idx < 2; idx++) { | 1743 | for (idx = 0; idx < 2; idx++) { |
| 1755 | if (! setup[idx] || setup[idx]->disable) | 1744 | if (setup[idx].disable) |
| 1756 | continue; | 1745 | continue; |
| 1757 | if (idx == SNDRV_PCM_STREAM_PLAYBACK) { | 1746 | if (idx == SNDRV_PCM_STREAM_PLAYBACK) { |
| 1758 | if (! (f_mode & FMODE_WRITE)) | 1747 | if (! (f_mode & FMODE_WRITE)) |
| @@ -1768,7 +1757,7 @@ static int snd_pcm_oss_open_file(struct file *file, | |||
| 1768 | } | 1757 | } |
| 1769 | 1758 | ||
| 1770 | pcm_oss_file->streams[idx] = substream; | 1759 | pcm_oss_file->streams[idx] = substream; |
| 1771 | snd_pcm_oss_init_substream(substream, setup[idx], minor); | 1760 | snd_pcm_oss_init_substream(substream, &setup[idx], minor); |
| 1772 | } | 1761 | } |
| 1773 | 1762 | ||
| 1774 | if (! pcm_oss_file->streams[0] && pcm_oss_file->streams[1]) { | 1763 | if (! pcm_oss_file->streams[0] && pcm_oss_file->streams[1]) { |
| @@ -1799,7 +1788,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
| 1799 | char task_name[32]; | 1788 | char task_name[32]; |
| 1800 | struct snd_pcm *pcm; | 1789 | struct snd_pcm *pcm; |
| 1801 | struct snd_pcm_oss_file *pcm_oss_file; | 1790 | struct snd_pcm_oss_file *pcm_oss_file; |
| 1802 | struct snd_pcm_oss_setup *setup[2]; | 1791 | struct snd_pcm_oss_setup setup[2]; |
| 1803 | int nonblock; | 1792 | int nonblock; |
| 1804 | wait_queue_t wait; | 1793 | wait_queue_t wait; |
| 1805 | 1794 | ||
| @@ -1822,9 +1811,11 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
| 1822 | } | 1811 | } |
| 1823 | memset(setup, 0, sizeof(*setup)); | 1812 | memset(setup, 0, sizeof(*setup)); |
| 1824 | if (file->f_mode & FMODE_WRITE) | 1813 | if (file->f_mode & FMODE_WRITE) |
| 1825 | setup[0] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name); | 1814 | snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
| 1815 | task_name, &setup[0]); | ||
| 1826 | if (file->f_mode & FMODE_READ) | 1816 | if (file->f_mode & FMODE_READ) |
| 1827 | setup[1] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name); | 1817 | snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, |
| 1818 | task_name, &setup[1]); | ||
| 1828 | 1819 | ||
| 1829 | nonblock = !!(file->f_flags & O_NONBLOCK); | 1820 | nonblock = !!(file->f_flags & O_NONBLOCK); |
| 1830 | if (!nonblock) | 1821 | if (!nonblock) |
| @@ -2249,13 +2240,8 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry, | |||
| 2249 | 2240 | ||
| 2250 | static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) | 2241 | static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) |
| 2251 | { | 2242 | { |
| 2252 | unsigned int idx; | ||
| 2253 | struct snd_pcm_substream *substream; | ||
| 2254 | struct snd_pcm_oss_setup *setup, *setupn; | 2243 | struct snd_pcm_oss_setup *setup, *setupn; |
| 2255 | 2244 | ||
| 2256 | for (idx = 0, substream = pstr->substream; | ||
| 2257 | idx < pstr->substream_count; idx++, substream = substream->next) | ||
| 2258 | substream->oss.setup = NULL; | ||
| 2259 | for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL; | 2245 | for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL; |
| 2260 | setup; setup = setupn) { | 2246 | setup; setup = setupn) { |
| 2261 | setupn = setup->next; | 2247 | setupn = setup->next; |
| @@ -2316,21 +2302,28 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, | |||
| 2316 | } | 2302 | } |
| 2317 | } while (*str); | 2303 | } while (*str); |
| 2318 | if (setup == NULL) { | 2304 | if (setup == NULL) { |
| 2319 | setup = kmalloc(sizeof(struct snd_pcm_oss_setup), GFP_KERNEL); | 2305 | setup = kmalloc(sizeof(*setup), GFP_KERNEL); |
| 2320 | if (setup) { | 2306 | if (! setup) { |
| 2321 | if (pstr->oss.setup_list == NULL) { | 2307 | buffer->error = -ENOMEM; |
| 2322 | pstr->oss.setup_list = setup; | 2308 | mutex_lock(&pstr->oss.setup_mutex); |
| 2323 | } else { | 2309 | return; |
| 2324 | for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next); | 2310 | } |
| 2325 | setup1->next = setup; | 2311 | if (pstr->oss.setup_list == NULL) |
| 2326 | } | 2312 | pstr->oss.setup_list = setup; |
| 2327 | template.task_name = kstrdup(task_name, GFP_KERNEL); | 2313 | else { |
| 2328 | } else { | 2314 | for (setup1 = pstr->oss.setup_list; |
| 2315 | setup1->next; setup1 = setup1->next); | ||
| 2316 | setup1->next = setup; | ||
| 2317 | } | ||
| 2318 | template.task_name = kstrdup(task_name, GFP_KERNEL); | ||
| 2319 | if (! template.task_name) { | ||
| 2320 | kfree(setup); | ||
| 2329 | buffer->error = -ENOMEM; | 2321 | buffer->error = -ENOMEM; |
| 2322 | mutex_lock(&pstr->oss.setup_mutex); | ||
| 2323 | return; | ||
| 2330 | } | 2324 | } |
| 2331 | } | 2325 | } |
| 2332 | if (setup) | 2326 | *setup = template; |
| 2333 | *setup = template; | ||
| 2334 | mutex_unlock(&pstr->oss.setup_mutex); | 2327 | mutex_unlock(&pstr->oss.setup_mutex); |
| 2335 | } | 2328 | } |
| 2336 | } | 2329 | } |
