30 #include <linux/slab.h>
31 #include <linux/time.h>
33 #include <linux/module.h>
35 #include <linux/string.h>
42 #include <linux/soundcard.h>
46 #define OSS_ALSAEMULVER _SIOR ('M', 249, int)
50 static bool nonblock_open = 1;
83 static int snd_interval_refine_min(
struct snd_interval *
i,
unsigned int min,
int openmin)
90 }
else if (i->
min == min && !i->
openmin && openmin) {
100 if (snd_interval_checkempty(i)) {
101 snd_interval_none(i);
107 static int snd_interval_refine_max(
struct snd_interval *i,
unsigned int max,
int openmax)
114 }
else if (i->
max == max && !i->
openmax && openmax) {
124 if (snd_interval_checkempty(i)) {
125 snd_interval_none(i);
131 static int snd_interval_refine_set(
struct snd_interval *i,
unsigned int val)
153 if (hw_is_mask(var)) {
156 return snd_mask_min(hw_param_mask_c(params, var));
158 if (hw_is_interval(var)) {
159 const struct snd_interval *i = hw_param_interval_c(params, var);
162 return snd_interval_min(i);
179 if (hw_is_mask(var)) {
182 return snd_mask_max(hw_param_mask_c(params, var));
184 if (hw_is_interval(var)) {
185 const struct snd_interval *i = hw_param_interval_c(params, var);
188 return snd_interval_max(i);
198 changed = snd_mask_refine(hw_param_mask(params, var), val);
200 params->
cmask |= 1 << var;
201 params->
rmask |= 1 << var;
211 int changed = _snd_pcm_hw_param_mask(params, var, val);
231 }
else if (dir < 0) {
239 changed = snd_mask_refine_min(hw_param_mask(params, var),
241 else if (hw_is_interval(var))
242 changed = snd_interval_refine_min(hw_param_interval(params, var),
247 params->
cmask |= 1 << var;
248 params->
rmask |= 1 << var;
270 int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
278 return snd_pcm_hw_param_value_min(params, var, dir);
290 }
else if (dir > 0) {
295 if (hw_is_mask(var)) {
296 if (val == 0 && open) {
297 snd_mask_none(hw_param_mask(params, var));
300 changed = snd_mask_refine_max(hw_param_mask(params, var),
302 }
else if (hw_is_interval(var))
303 changed = snd_interval_refine_max(hw_param_interval(params, var),
308 params->
cmask |= 1 << var;
309 params->
rmask |= 1 << var;
331 int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
339 return snd_pcm_hw_param_value_max(params, var, dir);
342 static int boundary_sub(
int a,
int adir,
346 adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
347 bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
352 }
else if (*cdir == 2) {
358 static int boundary_lt(
unsigned int a,
int adir,
359 unsigned int b,
int bdir)
371 return a < b || (a == b && adir < bdir);
375 static int boundary_nearer(
int min,
int mindir,
376 int best,
int bestdir,
381 boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
382 boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
383 return boundary_lt(dmin, dmindir, dmax, dmaxdir);
407 unsigned int saved_min;
411 int valdir = dir ? *dir : 0;
416 mindir = maxdir = valdir;
419 else if (maxdir == 0)
430 min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
435 if ((
unsigned int)min == saved_min && mindir == valdir)
438 if (params1 ==
NULL) {
443 max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
448 if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
455 max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
477 if (hw_is_mask(var)) {
478 struct snd_mask *
m = hw_param_mask(params, var);
479 if (val == 0 && dir < 0) {
487 changed = snd_mask_refine_set(hw_param_mask(params, var), val);
489 }
else if (hw_is_interval(var)) {
490 struct snd_interval *i = hw_param_interval(params, var);
491 if (val == 0 && dir < 0) {
493 snd_interval_none(i);
495 changed = snd_interval_refine_set(i, val);
514 params->
cmask |= 1 << var;
515 params->
rmask |= 1 << var;
537 int changed = _snd_pcm_hw_param_set(params, var, val, dir);
552 changed = snd_interval_setinteger(hw_param_interval(params, var));
554 params->
cmask |= 1 << var;
555 params->
rmask |= 1 << var;
564 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
568 struct snd_pcm_plugin *plugin, *
next;
570 plugin = runtime->oss.plugin_first;
576 runtime->oss.plugin_first = runtime->oss.plugin_last =
NULL;
580 static int snd_pcm_plugin_insert(
struct snd_pcm_plugin *plugin)
583 plugin->next = runtime->oss.plugin_first;
585 if (runtime->oss.plugin_first) {
586 runtime->oss.plugin_first->prev = plugin;
587 runtime->oss.plugin_first = plugin;
589 runtime->oss.plugin_last =
590 runtime->oss.plugin_first = plugin;
595 int snd_pcm_plugin_append(
struct snd_pcm_plugin *plugin)
599 plugin->prev = runtime->oss.plugin_last;
600 if (runtime->oss.plugin_last) {
601 runtime->oss.plugin_last->next = plugin;
602 runtime->oss.plugin_last = plugin;
604 runtime->oss.plugin_last =
605 runtime->oss.plugin_first = plugin;
614 long buffer_size = snd_pcm_lib_buffer_bytes(substream);
615 long bytes = frames_to_bytes(runtime, frames);
616 if (buffer_size == runtime->oss.buffer_bytes)
618 #if BITS_PER_LONG >= 64
619 return runtime->oss.buffer_bytes * bytes /
buffer_size;
623 return div_u64(bsize, buffer_size);
631 long buffer_size = snd_pcm_lib_buffer_bytes(substream);
632 if (buffer_size == runtime->oss.buffer_bytes)
633 return bytes_to_frames(runtime, bytes);
634 return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
645 #define AFMT_S32_LE 0x00001000
646 #define AFMT_S32_BE 0x00002000
647 #define AFMT_S24_LE 0x00008000
648 #define AFMT_S24_BE 0x00010000
649 #define AFMT_S24_PACKED 0x00040000
652 #define AFMT_FLOAT 0x00004000
653 #define AFMT_SPDIF_RAW 0x00020000
656 #define AFMT_AC3 0x00000400
657 #define AFMT_VORBIS 0x00000800
677 case AFMT_FLOAT:
return SNDRV_PCM_FORMAT_FLOAT;
701 case SNDRV_PCM_FORMAT_FLOAT:
return AFMT_FLOAT;
712 size_t oss_buffer_size, oss_period_size, oss_periods;
713 size_t min_period_size, max_period_size;
715 size_t oss_frame_size;
722 oss_buffer_size = 1 << ld2(oss_buffer_size);
724 if (oss_buffer_size > runtime->oss.mmap_bytes)
725 oss_buffer_size = runtime->oss.mmap_bytes;
728 if (substream->oss.setup.period_size > 16)
729 oss_period_size = substream->oss.setup.period_size;
730 else if (runtime->oss.fragshift) {
731 oss_period_size = 1 << runtime->oss.fragshift;
732 if (oss_period_size > oss_buffer_size / 2)
733 oss_period_size = oss_buffer_size / 2;
738 oss_period_size = oss_buffer_size;
740 oss_period_size /= 2;
741 }
while (oss_period_size > bytes_per_sec);
742 if (runtime->oss.subdivision == 0) {
744 if (oss_period_size / sd > 4096)
746 if (oss_period_size / sd < 4096)
749 sd = runtime->oss.subdivision;
750 oss_period_size /= sd;
751 if (oss_period_size < 16)
752 oss_period_size = 16;
757 min_period_size *= oss_frame_size;
758 min_period_size = 1 << (ld2(min_period_size - 1) + 1);
759 if (oss_period_size < min_period_size)
760 oss_period_size = min_period_size;
764 max_period_size *= oss_frame_size;
765 max_period_size = 1 << ld2(max_period_size);
766 if (oss_period_size > max_period_size)
767 oss_period_size = max_period_size;
769 oss_periods = oss_buffer_size / oss_period_size;
771 if (substream->oss.setup.periods > 1)
772 oss_periods = substream->oss.setup.periods;
775 if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
776 s = runtime->oss.maxfrags;
786 while (oss_period_size * oss_periods > oss_buffer_size)
787 oss_period_size /= 2;
789 if (oss_period_size < 16)
791 runtime->oss.period_bytes = oss_period_size;
792 runtime->oss.period_frames = 1;
793 runtime->oss.
periods = oss_periods;
817 ret = snd_pcm_hw_param_set(substream, params,
820 if (ret == (
int)rate) {
842 ssize_t oss_buffer_size, oss_period_size;
843 size_t oss_frame_size;
856 if (!sw_params || !params || !sparams) {
865 direct = substream->oss.setup.direct;
870 snd_mask_none(&
mask);
884 choose_rate(substream, sparams, runtime->oss.
rate);
887 format = snd_pcm_oss_format_from(runtime->oss.
format);
895 if ((
__force int)sformat < 0 ||
896 !snd_mask_test(&sformat_mask, (
__force int)sformat)) {
900 if (snd_mask_test(&sformat_mask, (
__force int)sformat) &&
901 snd_pcm_oss_format_to(sformat) >= 0)
915 memcpy(params, sparams,
sizeof(*params));
921 (
__force int)snd_pcm_oss_format_from(runtime->oss.
format), 0);
925 runtime->oss.
rate, 0);
926 pdprintf(
"client: access = %i, format = %i, channels = %i, rate = %i\n",
930 pdprintf(
"slave: access = %i, format = %i, channels = %i, rate = %i\n",
937 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
938 snd_pcm_oss_plugin_clear(substream);
941 snd_pcm_oss_plugin_clear(substream);
945 snd_printd(
"snd_pcm_plug_format_plugins failed: %i\n", err);
946 snd_pcm_oss_plugin_clear(substream);
949 if (runtime->oss.plugin_first) {
950 struct snd_pcm_plugin *plugin;
952 snd_printd(
"snd_pcm_plugin_build_io failed: %i\n", err);
953 snd_pcm_oss_plugin_clear(substream);
957 err = snd_pcm_plugin_append(plugin);
959 err = snd_pcm_plugin_insert(plugin);
962 snd_pcm_oss_plugin_clear(substream);
969 err = snd_pcm_oss_period_size(substream, params, sparams);
990 memset(sw_params, 0,
sizeof(*sw_params));
991 if (runtime->oss.trigger) {
1006 substream->oss.setup.nosilence) {
1025 if (oss_period_size < 0) {
1029 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
1030 if (runtime->oss.plugin_first) {
1036 oss_period_size *= oss_frame_size;
1038 oss_buffer_size = oss_period_size * runtime->oss.
periods;
1039 if (oss_buffer_size < 0) {
1044 runtime->oss.period_bytes = oss_period_size;
1045 runtime->oss.buffer_bytes = oss_buffer_size;
1047 pdprintf(
"oss: period bytes = %i, buffer bytes = %i\n",
1048 runtime->oss.period_bytes,
1049 runtime->oss.buffer_bytes);
1050 pdprintf(
"slave: period_size = %i, buffer_size = %i\n",
1058 vfree(runtime->oss.buffer);
1059 runtime->oss.buffer =
vmalloc(runtime->oss.period_bytes);
1060 if (!runtime->oss.buffer) {
1065 runtime->oss.params = 0;
1066 runtime->oss.prepare = 1;
1067 runtime->oss.buffer_used = 0;
1071 runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size);
1087 for (idx = 0; idx < 2; idx++) {
1089 if (substream ==
NULL)
1091 if (asubstream ==
NULL)
1092 asubstream = substream;
1093 if (substream->runtime->oss.params) {
1094 err = snd_pcm_oss_change_params(substream);
1102 *r_substream = asubstream;
1113 snd_printd(
"snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n");
1116 runtime->oss.prepare = 0;
1117 runtime->oss.prev_hw_ptr_period = 0;
1118 runtime->oss.period_ptr = 0;
1119 runtime->oss.buffer_used = 0;
1129 if (substream ==
NULL)
1132 if (runtime->oss.params) {
1133 err = snd_pcm_oss_change_params(substream);
1137 if (runtime->oss.prepare) {
1138 err = snd_pcm_oss_prepare(substream);
1180 "recovering from XRUN\n");
1183 "recovering from SUSPEND\n");
1185 ret = snd_pcm_oss_prepare(substream);
1191 fs = snd_enter_user();
1218 "recovering from XRUN\n");
1221 "recovering from SUSPEND\n");
1227 ret = snd_pcm_oss_prepare(substream);
1231 ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
1236 fs = snd_enter_user();
1242 if (ret == -
EPIPE) {
1266 "recovering from XRUN\n");
1269 "recovering from SUSPEND\n");
1271 ret = snd_pcm_oss_prepare(substream);
1277 fs = snd_enter_user();
1304 "recovering from XRUN\n");
1307 "recovering from SUSPEND\n");
1313 ret = snd_pcm_oss_prepare(substream);
1319 fs = snd_enter_user();
1335 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
1336 if (runtime->oss.plugin_first) {
1337 struct snd_pcm_plugin_channel *
channels;
1338 size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.
channels) / 8;
1342 buf = runtime->oss.buffer;
1344 frames = bytes / oss_frame_bytes;
1351 bytes = frames1 * oss_frame_bytes;
1355 frames = bytes_to_frames(runtime, bytes);
1359 bytes = frames_to_bytes(runtime, frames1);
1373 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
1377 if (bytes < runtime->
oss.period_bytes || runtime->oss.buffer_used > 0) {
1379 if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
1380 tmp = runtime->oss.period_bytes - runtime->oss.buffer_used;
1382 if (
copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) {
1387 runtime->oss.buffer_used +=
tmp;
1391 if (substream->oss.setup.partialfrag ||
1392 runtime->oss.buffer_used == runtime->oss.period_bytes) {
1393 tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr,
1394 runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
1397 runtime->oss.bytes +=
tmp;
1398 runtime->oss.period_ptr +=
tmp;
1399 runtime->oss.period_ptr %= runtime->oss.period_bytes;
1400 if (runtime->oss.period_ptr == 0 ||
1401 runtime->oss.period_ptr == runtime->oss.buffer_used)
1402 runtime->oss.buffer_used = 0;
1409 tmp = snd_pcm_oss_write2(substream,
1411 runtime->oss.period_bytes, 0);
1414 runtime->oss.bytes +=
tmp;
1419 tmp != runtime->oss.period_bytes)
1435 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
1437 if (runtime->oss.plugin_first) {
1438 struct snd_pcm_plugin_channel *
channels;
1439 size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.
channels) / 8;
1441 buf = runtime->oss.buffer;
1442 frames = bytes / oss_frame_bytes;
1449 bytes = frames1 * oss_frame_bytes;
1455 frames = bytes_to_frames(runtime, bytes);
1459 bytes = frames_to_bytes(runtime, frames1);
1473 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
1477 if (bytes < runtime->
oss.period_bytes || runtime->oss.buffer_used > 0) {
1478 if (runtime->oss.buffer_used == 0) {
1479 tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
1482 runtime->oss.bytes +=
tmp;
1483 runtime->oss.period_ptr =
tmp;
1484 runtime->oss.buffer_used =
tmp;
1487 if ((
size_t) tmp > runtime->oss.buffer_used)
1488 tmp = runtime->oss.buffer_used;
1489 if (
copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp)) {
1496 runtime->oss.buffer_used -=
tmp;
1498 tmp = snd_pcm_oss_read2(substream, (
char __force *)buf,
1499 runtime->oss.period_bytes, 0);
1502 runtime->oss.bytes +=
tmp;
1522 for (i = 0; i < 2; i++) {
1523 substream = pcm_oss_file->
streams[
i];
1528 runtime->oss.prepare = 1;
1529 runtime->oss.buffer_used = 0;
1530 runtime->oss.prev_hw_ptr_period = 0;
1531 runtime->oss.period_ptr = 0;
1542 if (substream !=
NULL) {
1543 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1561 init_waitqueue_entry(&wait,
current);
1567 result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);
1569 runtime->oss.buffer_used = 0;
1573 if (result != 0 && result != -
EAGAIN)
1577 snd_pcm_stream_lock_irq(substream);
1578 state = runtime->
status->state;
1579 snd_pcm_stream_unlock_irq(substream);
1585 if (signal_pending(
current)) {
1602 unsigned int saved_f_flags;
1606 unsigned long width;
1610 if (substream !=
NULL) {
1614 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1616 format = snd_pcm_oss_format_from(runtime->oss.
format);
1619 if (runtime->oss.buffer_used > 0) {
1623 size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) /
width;
1625 runtime->oss.buffer + runtime->oss.buffer_used,
1627 err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
1632 }
else if (runtime->oss.period_ptr > 0) {
1636 size = runtime->oss.period_bytes - runtime->oss.period_ptr;
1638 runtime->oss.buffer,
1640 err = snd_pcm_oss_sync1(substream, size);
1657 size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
1662 runtime->oss.buffer,
1665 fs = snd_enter_user();
1680 saved_f_flags = substream->
f_flags;
1683 substream->
f_flags = saved_f_flags;
1686 runtime->oss.prepare = 1;
1690 if (substream !=
NULL) {
1691 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1697 runtime->oss.buffer_used = 0;
1698 runtime->oss.prepare = 1;
1703 static int snd_pcm_oss_set_rate(
struct snd_pcm_oss_file *pcm_oss_file,
int rate)
1707 for (idx = 1; idx >= 0; --
idx) {
1710 if (substream ==
NULL)
1715 else if (rate > 192000)
1717 if (runtime->oss.
rate != rate) {
1718 runtime->oss.params = 1;
1722 return snd_pcm_oss_get_rate(pcm_oss_file);
1730 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1732 return substream->
runtime->oss.rate;
1735 static int snd_pcm_oss_set_channels(
struct snd_pcm_oss_file *pcm_oss_file,
unsigned int channels)
1742 for (idx = 1; idx >= 0; --
idx) {
1745 if (substream ==
NULL)
1748 if (runtime->oss.
channels != channels) {
1749 runtime->oss.params = 1;
1753 return snd_pcm_oss_get_channels(pcm_oss_file);
1761 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1763 return substream->
runtime->oss.channels;
1766 static int snd_pcm_oss_get_block_size(
struct snd_pcm_oss_file *pcm_oss_file)
1771 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1773 return substream->
runtime->oss.period_bytes;
1786 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1791 direct = substream->oss.setup.direct;
1809 for (fmt = 0; fmt < 32; ++
fmt) {
1810 if (snd_mask_test(&format_mask, fmt)) {
1811 int f = snd_pcm_oss_format_to(fmt);
1819 static int snd_pcm_oss_set_format(
struct snd_pcm_oss_file *pcm_oss_file,
int format)
1824 formats = snd_pcm_oss_get_formats(pcm_oss_file);
1827 if (!(formats & format))
1829 for (idx = 1; idx >= 0; --
idx) {
1832 if (substream ==
NULL)
1835 if (runtime->oss.
format != format) {
1836 runtime->oss.params = 1;
1841 return snd_pcm_oss_get_format(pcm_oss_file);
1849 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1851 return substream->
runtime->oss.format;
1854 static int snd_pcm_oss_set_subdivide1(
struct snd_pcm_substream *substream,
int subdivide)
1858 if (substream ==
NULL)
1861 if (subdivide == 0) {
1862 subdivide = runtime->oss.subdivision;
1867 if (runtime->oss.subdivision || runtime->oss.fragshift)
1869 if (subdivide != 1 && subdivide != 2 && subdivide != 4 &&
1870 subdivide != 8 && subdivide != 16)
1872 runtime->oss.subdivision = subdivide;
1873 runtime->oss.params = 1;
1877 static int snd_pcm_oss_set_subdivide(
struct snd_pcm_oss_file *pcm_oss_file,
int subdivide)
1881 for (idx = 1; idx >= 0; --
idx) {
1883 if (substream ==
NULL)
1885 if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0)
1891 static int snd_pcm_oss_set_fragment1(
struct snd_pcm_substream *substream,
unsigned int val)
1895 if (substream ==
NULL)
1898 if (runtime->oss.subdivision || runtime->oss.fragshift)
1900 runtime->oss.fragshift = val & 0xffff;
1901 runtime->oss.maxfrags = (val >> 16) & 0xffff;
1902 if (runtime->oss.fragshift < 4)
1903 runtime->oss.fragshift = 4;
1904 if (runtime->oss.maxfrags < 2)
1905 runtime->oss.maxfrags = 2;
1906 runtime->oss.params = 1;
1910 static int snd_pcm_oss_set_fragment(
struct snd_pcm_oss_file *pcm_oss_file,
unsigned int val)
1914 for (idx = 1; idx >= 0; --
idx) {
1916 if (substream ==
NULL)
1918 if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0)
1924 static int snd_pcm_oss_nonblock(
struct file *
file)
1926 spin_lock(&file->
f_lock);
1928 spin_unlock(&file->
f_lock);
1935 if (substream ==
NULL) {
1939 #ifdef DSP_CAP_MULTI
1941 if (substream->
pstr->substream_count > 1)
1946 #if defined(DSP_CAP_REALTIME) && 0
1961 for (idx = 0; idx < 2; idx++) {
1963 result = snd_pcm_oss_get_caps1(substream, result);
1993 if ((err = snd_pcm_oss_make_ready(psubstream)) < 0)
1997 if ((err = snd_pcm_oss_make_ready(csubstream)) < 0)
2001 runtime = psubstream->
runtime;
2003 if (runtime->oss.trigger)
2006 snd_pcm_oss_simulate_fill(psubstream,
2007 get_hw_ptr_period(runtime));
2008 runtime->oss.trigger = 1;
2012 if (!runtime->oss.trigger)
2014 runtime->oss.trigger = 0;
2017 runtime->oss.prepare = 1;
2025 runtime = csubstream->runtime;
2027 if (runtime->oss.trigger)
2029 runtime->oss.trigger = 1;
2033 if (!runtime->oss.trigger)
2035 runtime->oss.trigger = 0;
2038 runtime->oss.prepare = 1;
2055 if (psubstream && psubstream->
runtime && psubstream->
runtime->oss.trigger)
2057 if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
2070 if (substream ==
NULL)
2072 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
2075 if (runtime->oss.params || runtime->oss.prepare)
2082 return snd_pcm_oss_bytes(substream, delay);
2096 substream = pcm_oss_file->
streams[stream];
2097 if (substream ==
NULL)
2099 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
2102 if (runtime->oss.params || runtime->oss.prepare) {
2110 if (err == -
EPIPE || err == -
ESTRPIPE || (! err && delay < 0)) {
2115 fixup = runtime->oss.buffer_used;
2118 err = snd_pcm_oss_capture_position_fixup(substream, &delay);
2119 fixup = -runtime->oss.buffer_used;
2126 delay = get_hw_ptr_period(runtime);
2127 n = delay - runtime->oss.prev_hw_ptr_period;
2131 runtime->oss.prev_hw_ptr_period =
delay;
2133 snd_pcm_oss_simulate_fill(substream, delay);
2136 delay = snd_pcm_oss_bytes(substream, delay);
2138 if (substream->oss.setup.buggyptr)
2139 info.blocks = (runtime->oss.buffer_bytes - delay -
fixup) / runtime->oss.period_bytes;
2141 info.blocks = (delay + fixup) / runtime->oss.period_bytes;
2145 info.blocks = delay / runtime->oss.period_bytes;
2165 substream = pcm_oss_file->
streams[stream];
2166 if (substream ==
NULL)
2170 if (runtime->oss.params &&
2171 (err = snd_pcm_oss_change_params(substream)) < 0)
2174 info.fragsize = runtime->oss.period_bytes;
2176 if (runtime->oss.prepare) {
2178 info.bytes = runtime->oss.period_bytes * runtime->oss.
periods;
2187 if (err == -
EPIPE || err == -
ESTRPIPE || (! err && avail < 0)) {
2193 fixup = -runtime->oss.buffer_used;
2196 err = snd_pcm_oss_capture_position_fixup(substream, &avail);
2197 fixup = runtime->oss.buffer_used;
2201 info.bytes = snd_pcm_oss_bytes(substream, avail) +
fixup;
2202 info.fragments =
info.bytes / runtime->oss.period_bytes;
2207 "fragstotal = %i, fragsize = %i\n",
2222 static const char *strip_task_path(
const char *
path)
2224 const char *
ptr, *ptrl =
NULL;
2225 for (ptr = path; *
ptr; ptr++) {
2232 static void snd_pcm_oss_look_for_setup(
struct snd_pcm *pcm,
int stream,
2233 const char *task_name,
2240 for (setup = pcm->
streams[stream].oss.setup_list; setup;
2241 setup = setup->
next) {
2245 }
while ((task_name = strip_task_path(task_name)) !=
NULL);
2256 vfree(runtime->oss.buffer);
2257 runtime->oss.buffer =
NULL;
2258 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
2259 snd_pcm_oss_plugin_clear(substream);
2261 substream->oss.oss = 0;
2270 substream->oss.oss = 1;
2271 substream->oss.setup = *setup;
2274 else if (setup->
block)
2277 runtime->oss.params = 1;
2278 runtime->oss.trigger = 1;
2279 runtime->oss.
rate = 8000;
2281 switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
2282 case SNDRV_MINOR_OSS_PCM_8:
2285 case SNDRV_MINOR_OSS_PCM_16:
2292 runtime->oss.fragshift = 0;
2293 runtime->oss.maxfrags = 0;
2294 runtime->oss.subdivision = 0;
2295 substream->
pcm_release = snd_pcm_oss_release_substream;
2303 for (cidx = 0; cidx < 2; ++cidx) {
2308 kfree(pcm_oss_file);
2312 static int snd_pcm_oss_open_file(
struct file *
file,
2324 *rpcm_oss_file =
NULL;
2326 pcm_oss_file = kzalloc(
sizeof(*pcm_oss_file),
GFP_KERNEL);
2327 if (pcm_oss_file ==
NULL)
2335 for (idx = 0; idx < 2; idx++) {
2338 if (! pcm->
streams[idx].substream_count)
2349 snd_pcm_oss_release_file(pcm_oss_file);
2354 substream->
file = pcm_oss_file;
2355 snd_pcm_oss_init_substream(substream, &setup[idx], minor);
2359 snd_pcm_oss_release_file(pcm_oss_file);
2365 *rpcm_oss_file = pcm_oss_file;
2376 for (idx = 0; idx <
sizeof(task->
comm) && idx + 1 < size; idx++)
2377 name[idx] = task->
comm[idx];
2382 static int snd_pcm_oss_open(
struct inode *
inode,
struct file *file)
2396 pcm = snd_lookup_oss_minor_data(iminor(inode),
2397 SNDRV_OSS_DEVICE_TYPE_PCM);
2405 if (!try_module_get(pcm->
card->module)) {
2409 if (snd_task_name(
current, task_name,
sizeof(task_name)) < 0) {
2413 memset(setup, 0,
sizeof(setup));
2416 task_name, &setup[0]);
2419 task_name, &setup[1]);
2423 nonblock = nonblock_open;
2425 init_waitqueue_entry(&wait,
current);
2429 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
2430 iminor(inode), setup);
2444 if (pcm->
card->shutdown) {
2448 if (signal_pending(
current)) {
2461 module_put(pcm->
card->module);
2470 static int snd_pcm_oss_release(
struct inode *inode,
struct file *file)
2478 if (substream ==
NULL)
2482 pcm = substream->
pcm;
2483 if (!pcm->
card->shutdown)
2484 snd_pcm_oss_sync(pcm_oss_file);
2486 snd_pcm_oss_release_file(pcm_oss_file);
2489 module_put(pcm->
card->module);
2494 static long snd_pcm_oss_ioctl(
struct file *file,
unsigned int cmd,
unsigned long arg)
2505 #if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE))
2506 if (((cmd >> 8) & 0xff) ==
'M') {
2509 for (idx = 0; idx < 2; ++
idx) {
2511 if (substream !=
NULL)
2519 if (((cmd >> 8) & 0xff) !=
'P')
2526 return snd_pcm_oss_reset(pcm_oss_file);
2528 return snd_pcm_oss_sync(pcm_oss_file);
2532 if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0)
2536 res = snd_pcm_oss_get_rate(pcm_oss_file);
2543 res = res > 0 ? 2 : 1;
2544 if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0)
2548 res = snd_pcm_oss_get_block_size(pcm_oss_file);
2555 res = snd_pcm_oss_set_format(pcm_oss_file, res);
2560 res = snd_pcm_oss_get_format(pcm_oss_file);
2567 res = snd_pcm_oss_set_channels(pcm_oss_file, res);
2572 res = snd_pcm_oss_get_channels(pcm_oss_file);
2580 return snd_pcm_oss_post(pcm_oss_file);
2584 res = snd_pcm_oss_set_subdivide(pcm_oss_file, res);
2591 return snd_pcm_oss_set_fragment(pcm_oss_file, res);
2593 res = snd_pcm_oss_get_formats(pcm_oss_file);
2599 return snd_pcm_oss_get_space(pcm_oss_file,
2604 return snd_pcm_oss_nonblock(file);
2606 res = snd_pcm_oss_get_caps(pcm_oss_file);
2611 res = snd_pcm_oss_get_trigger(pcm_oss_file);
2618 return snd_pcm_oss_set_trigger(pcm_oss_file, res);
2621 return snd_pcm_oss_get_ptr(pcm_oss_file,
2627 return snd_pcm_oss_get_mapbuf(pcm_oss_file,
2639 res = snd_pcm_oss_get_odelay(pcm_oss_file);
2649 snd_printd(
"pcm_oss: unknown command = 0x%x\n", cmd);
2654 #ifdef CONFIG_COMPAT
2656 #define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl
2658 #define snd_pcm_oss_ioctl_compat NULL
2661 static ssize_t snd_pcm_oss_read(
struct file *file,
char __user *buf,
size_t count, loff_t *
offset)
2668 if (substream ==
NULL)
2672 return snd_pcm_oss_read1(substream, buf, count);
2675 ssize_t res = snd_pcm_oss_read1(substream, buf, count);
2677 "(returned %li bytes)\n", (
long)count, (
long)res);
2683 static ssize_t snd_pcm_oss_write(
struct file *file,
const char __user *buf,
size_t count, loff_t *
offset)
2691 if (substream ==
NULL)
2694 result = snd_pcm_oss_write1(substream, buf, count);
2697 (
long)count, (
long)result);
2706 return runtime->oss.prev_hw_ptr_period !=
2707 get_hw_ptr_period(runtime);
2709 return snd_pcm_playback_avail(runtime) >=
2710 runtime->oss.period_frames;
2717 return runtime->oss.prev_hw_ptr_period !=
2718 get_hw_ptr_period(runtime);
2720 return snd_pcm_capture_avail(runtime) >=
2721 runtime->oss.period_frames;
2724 static unsigned int snd_pcm_oss_poll(
struct file *file,
poll_table * wait)
2736 if (psubstream !=
NULL) {
2738 poll_wait(file, &runtime->
sleep, wait);
2739 snd_pcm_stream_lock_irq(psubstream);
2742 snd_pcm_oss_playback_ready(psubstream)))
2744 snd_pcm_stream_unlock_irq(psubstream);
2746 if (csubstream !=
NULL) {
2749 poll_wait(file, &runtime->
sleep, wait);
2750 snd_pcm_stream_lock_irq(csubstream);
2752 snd_pcm_oss_capture_ready(csubstream))
2754 snd_pcm_stream_unlock_irq(csubstream);
2757 memset(&ofile, 0,
sizeof(ofile));
2759 runtime->oss.trigger = 0;
2760 snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
2767 static int snd_pcm_oss_mmap(
struct file *file,
struct vm_area_struct *area)
2778 switch ((area->
vm_flags & (VM_READ | VM_WRITE))) {
2779 case VM_READ | VM_WRITE:
2796 if (substream ==
NULL)
2806 if (runtime->oss.params) {
2807 if ((err = snd_pcm_oss_change_params(substream)) < 0)
2810 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
2811 if (runtime->oss.plugin_first !=
NULL)
2826 runtime->oss.mmap_bytes);
2834 #ifdef CONFIG_SND_VERBOSE_PROCFS
2846 snd_iprintf(buffer,
"%s %u %u%s%s%s%s%s%s\n",
2850 setup->
disable ?
" disable" :
"",
2851 setup->
direct ?
" direct" :
"",
2852 setup->
block ?
" block" :
"",
2853 setup->
nonblock ?
" non-block" :
"",
2856 setup = setup->
next;
2861 static void snd_pcm_oss_proc_free_setup_list(
struct snd_pcm_str * pstr)
2865 for (setup = pstr->oss.setup_list, pstr->oss.setup_list =
NULL;
2866 setup; setup = setupn) {
2867 setupn = setup->
next;
2871 pstr->oss.setup_list =
NULL;
2878 char line[128],
str[32], task_name[32];
2883 while (!snd_info_get_line(buffer, line,
sizeof(line))) {
2885 memset(&
template, 0,
sizeof(
template));
2886 ptr = snd_info_get_str(task_name, line,
sizeof(task_name));
2887 if (!
strcmp(task_name,
"clear") || !
strcmp(task_name,
"erase")) {
2888 snd_pcm_oss_proc_free_setup_list(pstr);
2892 for (setup = pstr->oss.setup_list; setup; setup = setup->
next) {
2898 ptr = snd_info_get_str(str, ptr,
sizeof(str));
2900 ptr = snd_info_get_str(str, ptr,
sizeof(str));
2902 for (idx1 = 31; idx1 >= 0; idx1--)
2905 for (idx1--; idx1 >= 0; idx1--)
2908 ptr = snd_info_get_str(str, ptr,
sizeof(str));
2909 if (!
strcmp(str,
"disable")) {
2910 template.disable = 1;
2911 }
else if (!
strcmp(str,
"direct")) {
2912 template.direct = 1;
2913 }
else if (!
strcmp(str,
"block")) {
2915 }
else if (!
strcmp(str,
"non-block")) {
2916 template.nonblock = 1;
2917 }
else if (!
strcmp(str,
"partial-frag")) {
2918 template.partialfrag = 1;
2919 }
else if (!
strcmp(str,
"no-silence")) {
2920 template.nosilence = 1;
2921 }
else if (!
strcmp(str,
"buggy-ptr")) {
2922 template.buggyptr = 1;
2925 if (setup ==
NULL) {
2932 if (pstr->oss.setup_list ==
NULL)
2933 pstr->oss.setup_list = setup;
2935 for (setup1 = pstr->oss.setup_list;
2936 setup1->
next; setup1 = setup1->
next);
2937 setup1->
next = setup;
2940 if (!
template.task_name) {
2955 for (stream = 0; stream < 2; ++stream) {
2960 if ((entry = snd_info_create_card_entry(pcm->
card,
"oss", pstr->proc_root)) !=
NULL) {
2963 entry->
c.
text.read = snd_pcm_oss_proc_read;
2964 entry->
c.
text.write = snd_pcm_oss_proc_write;
2966 if (snd_info_register(entry) < 0) {
2967 snd_info_free_entry(entry);
2971 pstr->oss.proc_entry =
entry;
2978 for (stream = 0; stream < 2; ++stream) {
2980 snd_info_free_entry(pstr->oss.proc_entry);
2981 pstr->oss.proc_entry =
NULL;
2982 snd_pcm_oss_proc_free_setup_list(pstr);
2986 #define snd_pcm_oss_proc_init(pcm)
2987 #define snd_pcm_oss_proc_done(pcm)
2997 .read = snd_pcm_oss_read,
2998 .write = snd_pcm_oss_write,
2999 .open = snd_pcm_oss_open,
3000 .release = snd_pcm_oss_release,
3002 .poll = snd_pcm_oss_poll,
3003 .unlocked_ioctl = snd_pcm_oss_ioctl,
3005 .mmap = snd_pcm_oss_mmap,
3008 static void register_oss_dsp(
struct snd_pcm *pcm,
int index)
3012 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3013 pcm->
card, index, &snd_pcm_oss_f_reg,
3020 static int snd_pcm_oss_register_minor(
struct snd_pcm *pcm)
3023 if (dsp_map[pcm->
card->number] == (
int)pcm->
device) {
3026 register_oss_dsp(pcm, 0);
3030 sprintf(name,
"%s%s", pcm->
name, duplex ?
" (DUPLEX)" :
"");
3031 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
3032 snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO,
3037 pcm->oss.reg_mask |= 1;
3039 if (adsp_map[pcm->
card->number] == (
int)pcm->
device) {
3040 register_oss_dsp(pcm, 1);
3042 pcm->oss.reg_mask |= 2;
3051 static int snd_pcm_oss_disconnect_minor(
struct snd_pcm *pcm)
3054 if (pcm->oss.reg_mask & 1) {
3055 pcm->oss.reg_mask &= ~1;
3056 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3059 if (pcm->oss.reg_mask & 2) {
3060 pcm->oss.reg_mask &= ~2;
3061 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3064 if (dsp_map[pcm->
card->number] == (
int)pcm->
device) {
3065 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
3066 snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->
card->number);
3074 static int snd_pcm_oss_unregister_minor(
struct snd_pcm *pcm)
3076 snd_pcm_oss_disconnect_minor(pcm);
3083 .n_register = snd_pcm_oss_register_minor,
3084 .n_disconnect = snd_pcm_oss_disconnect_minor,
3085 .n_unregister = snd_pcm_oss_unregister_minor,
3088 static int __init alsa_pcm_oss_init(
void)
3111 static void __exit alsa_pcm_oss_exit(
void)