diff --git a/Kernel/Devices/SB16.cpp b/Kernel/Devices/SB16.cpp index 9723fdb062..bebc4bd3d7 100644 --- a/Kernel/Devices/SB16.cpp +++ b/Kernel/Devices/SB16.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace Kernel { @@ -49,6 +50,8 @@ u8 SB16::dsp_read() /* Changes the sample rate of sound output */ void SB16::set_sample_rate(uint16_t hz) { + dbgln("SB16: Changing sample rate to {} Hz", hz); + m_sample_rate = hz; dsp_write(0x41); // output dsp_write((u8)(hz >> 8)); dsp_write((u8)hz); @@ -115,6 +118,30 @@ UNMAP_AFTER_INIT void SB16::initialize() dmesgln("SB16: Found version {}.{}", m_major_version, vmin); set_irq_register(SB16_DEFAULT_IRQ); dmesgln("SB16: IRQ {}", get_irq_line()); + + set_sample_rate(m_sample_rate); +} + +KResult SB16::ioctl(FileDescription&, unsigned request, Userspace arg) +{ + switch (request) { + case SOUNDCARD_IOCTL_GET_SAMPLE_RATE: { + auto output = static_ptr_cast(arg); + if (!copy_to_user(output, &m_sample_rate)) + return EFAULT; + return KSuccess; + } + case SOUNDCARD_IOCTL_SET_SAMPLE_RATE: { + auto sample_rate_value = static_cast(arg.ptr()); + if (sample_rate_value == 0) + return EINVAL; + if (m_sample_rate != sample_rate_value) + set_sample_rate(sample_rate_value); + return KSuccess; + } + default: + return EINVAL; + } } void SB16::set_irq_register(u8 irq_number) @@ -256,8 +283,6 @@ KResultOr SB16::write(FileDescription&, u64, UserOrKernelBuffer const& d u8 mode = (u8)SampleFormat::Signed | (u8)SampleFormat::Stereo; - const int sample_rate = 44100; - set_sample_rate(sample_rate); if (!data.read(m_dma_region->vaddr().as_ptr(), length)) return EFAULT; dma_start(length); diff --git a/Kernel/Devices/SB16.h b/Kernel/Devices/SB16.h index 523d2d980a..0d8597eb72 100644 --- a/Kernel/Devices/SB16.h +++ b/Kernel/Devices/SB16.h @@ -38,6 +38,8 @@ public: virtual mode_t required_mode() const override { return 0220; } virtual String device_name() const override { return "audio"; } + virtual KResult ioctl(FileDescription&, unsigned, Userspace) override; + private: // ^IRQHandler virtual bool handle_irq(const RegisterState&) override; @@ -57,6 +59,7 @@ private: OwnPtr m_dma_region; int m_major_version { 0 }; + u16 m_sample_rate { 44100 }; WaitQueue m_irq_queue; }; diff --git a/Userland/Libraries/LibC/sys/ioctl_numbers.h b/Userland/Libraries/LibC/sys/ioctl_numbers.h index 78a4ba0eae..577e912ecb 100644 --- a/Userland/Libraries/LibC/sys/ioctl_numbers.h +++ b/Userland/Libraries/LibC/sys/ioctl_numbers.h @@ -87,6 +87,8 @@ enum IOCtlNumber { KCOV_SETBUFSIZE, KCOV_ENABLE, KCOV_DISABLE, + SOUNDCARD_IOCTL_SET_SAMPLE_RATE, + SOUNDCARD_IOCTL_GET_SAMPLE_RATE }; #define TIOCGPGRP TIOCGPGRP @@ -128,3 +130,5 @@ enum IOCtlNumber { #define FIBMAP FIBMAP #define FIONBIO FIONBIO #define FIONREAD FIONREAD +#define SOUNDCARD_IOCTL_SET_SAMPLE_RATE SOUNDCARD_IOCTL_SET_SAMPLE_RATE +#define SOUNDCARD_IOCTL_GET_SAMPLE_RATE SOUNDCARD_IOCTL_GET_SAMPLE_RATE