1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 08:24:58 +00:00
serenity/Kernel/Devices/Generic/PCSpeakerDevice.cpp
Liav A 1b00618fd9 Kernel+Userland: Replace the beep syscall with the new /dev/beep device
There's no need to have separate syscall for this kind of functionality,
as we can just have a device node in /dev, called "beep", that allows
writing tone generation packets to emulate the same behavior.

In addition to that, we remove LibC sysbeep function, as this function
was never being used by any C program nor it was standardized in any
way.
Instead, we move the userspace implementation to LibCore.
2023-11-03 15:19:33 +01:00

63 lines
1.8 KiB
C++

/*
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/API/BeepInstruction.h>
#if ARCH(X86_64)
# include <Kernel/Arch/x86_64/PCSpeaker.h>
#endif
#include <Kernel/Boot/CommandLine.h>
#include <Kernel/Devices/DeviceManagement.h>
#include <Kernel/Devices/Generic/PCSpeakerDevice.h>
#include <Kernel/Sections.h>
namespace Kernel {
UNMAP_AFTER_INIT NonnullRefPtr<PCSpeakerDevice> PCSpeakerDevice::must_create()
{
auto device = MUST(DeviceManagement::try_create_device<PCSpeakerDevice>());
return *device;
}
UNMAP_AFTER_INIT PCSpeakerDevice::PCSpeakerDevice()
: CharacterDevice(1, 10)
{
}
UNMAP_AFTER_INIT PCSpeakerDevice::~PCSpeakerDevice() = default;
bool PCSpeakerDevice::can_read(OpenFileDescription const&, u64) const
{
return true;
}
ErrorOr<size_t> PCSpeakerDevice::read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t)
{
return Error::from_errno(ENOTIMPL);
}
ErrorOr<size_t> PCSpeakerDevice::write(OpenFileDescription&, u64, UserOrKernelBuffer const& buffer, size_t buffer_size)
{
if (!kernel_command_line().is_pc_speaker_enabled())
return Error::from_errno(ENOTSUP);
if (buffer_size % sizeof(BeepInstruction) != 0)
return Error::from_errno(EINVAL);
BeepInstruction instruction {};
TRY(buffer.read(&instruction, sizeof(BeepInstruction)));
if (instruction.tone < 20 || instruction.tone > 20000)
return Error::from_errno(EINVAL);
#if ARCH(X86_64)
PCSpeaker::tone_on(instruction.tone);
auto result = Thread::current()->sleep(Duration::from_nanoseconds(200'000'000));
PCSpeaker::tone_off();
if (result.was_interrupted())
return Error::from_errno(EINTR);
return sizeof(BeepInstruction);
#else
return Error::from_errno(ENOTIMPL);
#endif
}
}