From bda276f498e355073eafb938eade0ba55c761872 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Wed, 27 Jul 2022 10:58:11 +0200 Subject: [PATCH] vfs_oss: implement 'SNDCTL_DSP_SETTRIGGER' command Fixes #4579 --- repos/libports/src/lib/libc/vfs_plugin.cc | 36 ++++++++- repos/libports/src/lib/vfs/oss/README | 8 ++ repos/libports/src/lib/vfs/oss/vfs_oss.cc | 95 ++++++++++++++++++++--- 3 files changed, 129 insertions(+), 10 deletions(-) diff --git a/repos/libports/src/lib/libc/vfs_plugin.cc b/repos/libports/src/lib/libc/vfs_plugin.cc index 56abd0d337..7ffc3dacbc 100644 --- a/repos/libports/src/lib/libc/vfs_plugin.cc +++ b/repos/libports/src/lib/libc/vfs_plugin.cc @@ -1682,7 +1682,41 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char if (!argp) return { true, EINVAL }; - /* dummy implementation */ + int mask = *(int *)argp; + + if (((fd->flags & O_ACCMODE) == O_RDONLY) || + ((fd->flags & O_ACCMODE) == O_RDWR)) { + + char enable_input_string[2]; + + ::snprintf(enable_input_string, sizeof(enable_input_string), + "%u", (mask & PCM_ENABLE_INPUT) ? 1 : 0); + + Absolute_path enable_input_path = ioctl_dir(*fd); + enable_input_path.append_element("enable_input"); + File_descriptor *enable_input_fd = open(enable_input_path.base(), O_WRONLY); + if (!enable_input_fd) + return { true, ENOTSUP }; + write(enable_input_fd, enable_input_string, sizeof(enable_input_string)); + close(enable_input_fd); + } + + if (((fd->flags & O_ACCMODE) == O_WRONLY) || + ((fd->flags & O_ACCMODE) == O_RDWR)) { + + char enable_output_string[2]; + + ::snprintf(enable_output_string, sizeof(enable_output_string), + "%u", (mask & PCM_ENABLE_OUTPUT) ? 1 : 0); + + Absolute_path enable_output_path = ioctl_dir(*fd); + enable_output_path.append_element("enable_output"); + File_descriptor *enable_output_fd = open(enable_output_path.base(), O_WRONLY); + if (!enable_output_fd) + return { true, ENOTSUP }; + write(enable_output_fd, enable_output_string, sizeof(enable_output_string)); + close(enable_output_fd); + } handled = true; diff --git a/repos/libports/src/lib/vfs/oss/README b/repos/libports/src/lib/vfs/oss/README index 3f66208634..799643e29a 100644 --- a/repos/libports/src/lib/vfs/oss/README +++ b/repos/libports/src/lib/vfs/oss/README @@ -71,6 +71,14 @@ presents all files: * halt_output (wo): writing anything into this file halts output processing. Corresponding OSS commands: SNDCTL_DSP_HALT + * enable_input (rw): writing 1 or 0 into this file enables or disables + input processing. + Corresponding OSS commands: SNDCTL_DSP_SETTRIGGER + + * enable_output (rw): writing 1 or 0 into this file enables or disables + output processing. + Corresponding OSS commands: SNDCTL_DSP_SETTRIGGER + In its current state the plugin is merely enough to use simple applications requiring nothing more than a minimal set of the OSSv4 API. It does not allow altering of all parameters and will only work when 44100Hz/s16le is used. diff --git a/repos/libports/src/lib/vfs/oss/vfs_oss.cc b/repos/libports/src/lib/vfs/oss/vfs_oss.cc index 806b530da8..9939e8b338 100644 --- a/repos/libports/src/lib/vfs/oss/vfs_oss.cc +++ b/repos/libports/src/lib/vfs/oss/vfs_oss.cc @@ -193,6 +193,9 @@ struct Vfs::Oss_file_system::Audio Audio(Audio const &); Audio &operator = (Audio const &); + bool _audio_out_enabled { true }; + bool _audio_in_enabled { true }; + bool _audio_out_started { false }; bool _audio_in_started { false }; @@ -208,6 +211,23 @@ struct Vfs::Oss_file_system::Audio size_t _read_sample_offset { 0 }; size_t _write_sample_offset { 0 }; + void _start_input() + { + if (!_audio_in_started && _audio_in_enabled) { + _in->start(); + _audio_in_started = true; + } + } + + void _start_output() + { + if (!_audio_out_started && _audio_out_enabled) { + _out[0]->start(); + _out[1]->start(); + _audio_out_started = true; + } + } + public: Audio(Genode::Env &env, @@ -302,6 +322,28 @@ struct Vfs::Oss_file_system::Audio } } + void enable_input(bool enable) + { + if (enable) { + _audio_in_enabled = true; + _start_input(); + } else { + halt_input(); + _audio_in_enabled = false; + } + } + + void enable_output(bool enable) + { + if (enable) { + _audio_out_enabled = true; + _start_output(); + } else { + halt_output(); + _audio_out_enabled = false; + } + } + /* * Handle Audio_out progress signal. * @@ -404,10 +446,7 @@ struct Vfs::Oss_file_system::Audio { out_size = 0; - if (!_audio_in_started) { - _in->start(); - _audio_in_started = true; - } + _start_input(); if (_info.ifrag_bytes == 0) { /* block */ @@ -493,11 +532,7 @@ struct Vfs::Oss_file_system::Audio return false; } - if (!_audio_out_started) { - _audio_out_started = true; - _out[0]->start(); - _out[1]->start(); - } + _start_output(); unsigned stream_samples_written = 0; @@ -756,6 +791,8 @@ struct Vfs::Oss_file_system::Local_factory : File_system_factory Readonly_value_file_system _optr_samples_fs { "optr_samples", 0LL }; Readonly_value_file_system _optr_fifo_samples_fs { "optr_fifo_samples", 0U }; Value_file_system _play_underruns_fs { "play_underruns", 0U }; + Value_file_system _enable_input_fs { "enable_input", 1U }; + Value_file_system _enable_output_fs { "enable_output", 1U }; /* WO files */ Value_file_system _halt_input_fs { "halt_input", 0U }; @@ -773,6 +810,18 @@ struct Vfs::Oss_file_system::Local_factory : File_system_factory Audio _audio { _env.env(), _info, _info_fs }; + Genode::Watch_handler _enable_input_handler { + _enable_input_fs, "/enable_input", + _env.alloc(), + *this, + &Vfs::Oss_file_system::Local_factory::_enable_input_changed }; + + Genode::Watch_handler _enable_output_handler { + _enable_output_fs, "/enable_output", + _env.alloc(), + *this, + &Vfs::Oss_file_system::Local_factory::_enable_output_changed }; + Genode::Watch_handler _halt_input_handler { _halt_input_fs, "/halt_input", _env.alloc(), @@ -829,6 +878,18 @@ struct Vfs::Oss_file_system::Local_factory : File_system_factory ** Watch handlers ** ********************/ + void _enable_input_changed() + { + bool enable = (bool)_enable_input_fs.value(); + _audio.enable_input(enable); + } + + void _enable_output_changed() + { + bool enable = (bool)_enable_output_fs.value(); + _audio.enable_output(enable); + } + void _halt_input_changed() { _audio.halt_input(); @@ -988,6 +1049,14 @@ struct Vfs::Oss_file_system::Local_factory : File_system_factory if (node.has_type(Value_file_system::type_name())) { + if (_enable_input_fs.matches(node)) { + return &_enable_input_fs; + } + + if (_enable_output_fs.matches(node)) { + return &_enable_output_fs; + } + if (_halt_input_fs.matches(node)) { return &_halt_input_fs; } @@ -1060,6 +1129,14 @@ class Vfs::Oss_file_system::Compound_file_system : private Local_factory, xml.attribute("name", "format"); }); + xml.node("value", [&] { + xml.attribute("name", "enable_input"); + }); + + xml.node("value", [&] { + xml.attribute("name", "enable_output"); + }); + xml.node("value", [&] { xml.attribute("name", "halt_input"); });