Files
banan-os/kernel/kernel/Audio/Controller.cpp
DcraftBg 647d6a273d Kernel: Changed stat values from func to be field
- Removed virtual functions for all of the stat stuff.
This did however introduce some issues, mainly with /proc
becoming out of sync if you changed your ID. I propose we
do the linux thing and just have a stat update function
which is optional, but allows dynamic updates of stat fields
for cases such as those in uid/gid in /proc.
- Simplified the API, although still kind of annoying
it is a bit simpler.
- Moved some of the FS structure from having the FS inode inside
the in memory inode to a Serialise <-> Deserialise model where
Inodes are deserialised from disk into in memory ones and then
back into on disk ones when it comes time for syncing.
This makes it semantically better in my opinion, as it explicitly
separates disk and non-disk functionality.
2026-05-15 20:49:04 +03:00

120 lines
3.2 KiB
C++

#include <kernel/Audio/AC97/Controller.h>
#include <kernel/Audio/Controller.h>
#include <kernel/Audio/HDAudio/Controller.h>
#include <kernel/Device/DeviceNumbers.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <sys/ioctl.h>
#include <sys/sysmacros.h>
namespace Kernel
{
static BAN::Atomic<dev_t> s_next_audio_minor = 0;
AudioController::AudioController()
: CharacterDevice(0644, 0, 0)
{
m_rdev = makedev(DeviceNumber::AudioController, s_next_audio_minor++);
char* ptr = m_name;
BAN::Formatter::print([&ptr](char c) { *ptr++ = c; }, "audio{}", minor(m_rdev));
}
BAN::ErrorOr<void> AudioController::create(PCI::Device& pci_device)
{
switch (pci_device.subclass())
{
case 0x01:
// We should confirm that the card is actually AC97 but I'm trusting osdev wiki on this one
// > you can probably expect that every sound card with subclass 0x01 is sound card compatibile with AC97
if (auto ret = AC97AudioController::create(pci_device); ret.is_error())
{
dwarnln("Failed to initialize AC97: {}", ret.error());
return ret.release_error();
}
break;
case 0x03:
if (auto ret = HDAudioController::create(pci_device); ret.is_error())
{
dwarnln("Failed to initialize Intel HDA: {}", ret.error());
return ret.release_error();
}
break;
default:
dprintln("Unsupported Sound card (PCI {2H}:{2H}:{2H})",
pci_device.class_code(),
pci_device.subclass(),
pci_device.prog_if()
);
return BAN::Error::from_errno(ENOTSUP);
}
return {};
}
BAN::ErrorOr<void> AudioController::initialize()
{
m_sample_data = TRY(ByteRingBuffer::create(m_sample_data_capacity));
return {};
}
BAN::ErrorOr<size_t> AudioController::write_impl(off_t, BAN::ConstByteSpan buffer)
{
SpinLockGuard lock_guard(m_spinlock);
while (m_sample_data->full())
{
SpinLockGuardAsMutex smutex(lock_guard);
TRY(Thread::current().block_or_eintr_indefinite(m_sample_data_blocker, &smutex));
}
const size_t to_copy = BAN::Math::min(buffer.size(), m_sample_data->free());
m_sample_data->push(buffer.slice(0, to_copy));
handle_new_data();
return to_copy;
}
BAN::ErrorOr<long> AudioController::ioctl_impl(int cmd, void* arg)
{
switch (cmd)
{
case SND_GET_CHANNELS:
*static_cast<uint32_t*>(arg) = get_channels();
return 0;
case SND_GET_SAMPLE_RATE:
*static_cast<uint32_t*>(arg) = get_sample_rate();
return 0;
case SND_RESET_BUFFER:
case SND_GET_BUFFERSZ:
{
SpinLockGuard _(m_spinlock);
*static_cast<uint32_t*>(arg) = m_sample_data->size();
if (cmd == SND_RESET_BUFFER)
m_sample_data->pop(m_sample_data->size());
return 0;
}
case SND_GET_TOTAL_PINS:
*static_cast<uint32_t*>(arg) = get_total_pins();
return 0;
case SND_GET_PIN:
*static_cast<uint32_t*>(arg) = get_current_pin();
return 0;
case SND_SET_PIN:
TRY(set_current_pin(*static_cast<uint32_t*>(arg)));
return 0;
case SND_GET_VOLUME_INFO:
*static_cast<snd_volume_info*>(arg) = m_volume_info;
return 0;
case SND_SET_VOLUME_MDB:
TRY(set_volume_mdB(*static_cast<int32_t*>(arg)));
return 0;
}
return CharacterDevice::ioctl_impl(cmd, arg);
}
}