mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
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.
This commit is contained in:
parent
ac70abcb73
commit
1b00618fd9
Notes:
sideshowbarker
2024-07-17 09:56:35 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/1b00618fd9 Pull-request: https://github.com/SerenityOS/serenity/pull/20761 Reviewed-by: https://github.com/timschumi ✅
16 changed files with 128 additions and 58 deletions
13
Kernel/API/BeepInstruction.h
Normal file
13
Kernel/API/BeepInstruction.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Types.h>
|
||||
|
||||
struct BeepInstruction {
|
||||
u16 tone;
|
||||
};
|
|
@ -51,7 +51,6 @@ enum class NeedsBigProcessLock {
|
|||
S(allocate_tls, NeedsBigProcessLock::Yes) \
|
||||
S(anon_create, NeedsBigProcessLock::No) \
|
||||
S(annotate_mapping, NeedsBigProcessLock::No) \
|
||||
S(beep, NeedsBigProcessLock::No) \
|
||||
S(bind, NeedsBigProcessLock::No) \
|
||||
S(bindmount, NeedsBigProcessLock::No) \
|
||||
S(chdir, NeedsBigProcessLock::No) \
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <Kernel/Devices/Generic/FullDevice.h>
|
||||
#include <Kernel/Devices/Generic/MemoryDevice.h>
|
||||
#include <Kernel/Devices/Generic/NullDevice.h>
|
||||
#include <Kernel/Devices/Generic/PCSpeakerDevice.h>
|
||||
#include <Kernel/Devices/Generic/RandomDevice.h>
|
||||
#include <Kernel/Devices/Generic/SelfTTYDevice.h>
|
||||
#include <Kernel/Devices/Generic/ZeroDevice.h>
|
||||
|
@ -380,6 +381,8 @@ void init_stage2(void*)
|
|||
(void)MUST(RPi::MiniUART::create()).leak_ref();
|
||||
#endif
|
||||
|
||||
(void)PCSpeakerDevice::must_create().leak_ref();
|
||||
|
||||
#if ARCH(X86_64)
|
||||
VMWareBackdoor::the(); // don't wait until first mouse packet
|
||||
#endif
|
||||
|
|
|
@ -80,6 +80,7 @@ set(KERNEL_SOURCES
|
|||
Devices/Generic/FullDevice.cpp
|
||||
Devices/Generic/MemoryDevice.cpp
|
||||
Devices/Generic/NullDevice.cpp
|
||||
Devices/Generic/PCSpeakerDevice.cpp
|
||||
Devices/Generic/RandomDevice.cpp
|
||||
Devices/Generic/SelfTTYDevice.cpp
|
||||
Devices/Generic/ZeroDevice.cpp
|
||||
|
@ -281,7 +282,6 @@ set(KERNEL_SOURCES
|
|||
Security/UBSanitizer.cpp
|
||||
Syscalls/anon_create.cpp
|
||||
Syscalls/alarm.cpp
|
||||
Syscalls/beep.cpp
|
||||
Syscalls/chdir.cpp
|
||||
Syscalls/chmod.cpp
|
||||
Syscalls/chown.cpp
|
||||
|
|
63
Kernel/Devices/Generic/PCSpeakerDevice.cpp
Normal file
63
Kernel/Devices/Generic/PCSpeakerDevice.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
||||
|
||||
}
|
36
Kernel/Devices/Generic/PCSpeakerDevice.h
Normal file
36
Kernel/Devices/Generic/PCSpeakerDevice.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/Devices/CharacterDevice.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class PCSpeakerDevice final : public CharacterDevice {
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
virtual ~PCSpeakerDevice() override;
|
||||
|
||||
static NonnullRefPtr<PCSpeakerDevice> must_create();
|
||||
|
||||
private:
|
||||
PCSpeakerDevice();
|
||||
|
||||
// ^Device
|
||||
virtual bool is_openable_by_jailed_processes() const override { return true; }
|
||||
|
||||
// ^CharacterDevice
|
||||
virtual ErrorOr<size_t> read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override;
|
||||
virtual ErrorOr<size_t> write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) override;
|
||||
virtual bool can_write(OpenFileDescription const&, u64) const override { return true; }
|
||||
virtual bool can_read(OpenFileDescription const&, u64) const override;
|
||||
virtual StringView class_name() const override { return "PCSpeakerDevice"sv; }
|
||||
virtual bool is_seekable() const override { return true; }
|
||||
};
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Boot/CommandLine.h>
|
||||
#if ARCH(X86_64)
|
||||
# include <Kernel/Arch/x86_64/PCSpeaker.h>
|
||||
#endif
|
||||
#include <Kernel/Tasks/Process.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<FlatPtr> Process::sys$beep(int tone)
|
||||
{
|
||||
VERIFY_NO_PROCESS_BIG_LOCK(this);
|
||||
if (!kernel_command_line().is_pc_speaker_enabled())
|
||||
return ENODEV;
|
||||
if (tone < 20 || tone > 20000)
|
||||
return EINVAL;
|
||||
#if ARCH(X86_64)
|
||||
PCSpeaker::tone_on(tone);
|
||||
auto result = Thread::current()->sleep(Duration::from_nanoseconds(200'000'000));
|
||||
PCSpeaker::tone_off();
|
||||
if (result.was_interrupted())
|
||||
return EINTR;
|
||||
return 0;
|
||||
#else
|
||||
return ENOTIMPL;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
|
@ -145,7 +145,6 @@ private:
|
|||
int virt$accept4(FlatPtr);
|
||||
u32 virt$allocate_tls(FlatPtr, size_t);
|
||||
int virt$anon_create(size_t, int);
|
||||
int virt$beep();
|
||||
int virt$bind(int sockfd, FlatPtr address, socklen_t address_length);
|
||||
u32 virt$bindmount(u32 params_addr);
|
||||
int virt$chdir(FlatPtr, size_t);
|
||||
|
|
|
@ -47,8 +47,6 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
|
|||
return virt$anon_create(arg1, arg2);
|
||||
case SC_annotate_mapping:
|
||||
return virt$annotate_mapping(arg1);
|
||||
case SC_beep:
|
||||
return virt$beep();
|
||||
case SC_bind:
|
||||
return virt$bind(arg1, arg2, arg3);
|
||||
case SC_bindmount:
|
||||
|
@ -1606,11 +1604,6 @@ u32 Emulator::virt$allocate_tls(FlatPtr initial_data, size_t size)
|
|||
return tls_base;
|
||||
}
|
||||
|
||||
int Emulator::virt$beep()
|
||||
{
|
||||
return syscall(SC_beep);
|
||||
}
|
||||
|
||||
u32 Emulator::virt$sysconf(u32 name)
|
||||
{
|
||||
return syscall(SC_sysconf, name);
|
||||
|
|
|
@ -925,12 +925,6 @@ int gettid()
|
|||
return cached_tid;
|
||||
}
|
||||
|
||||
int sysbeep(int tone)
|
||||
{
|
||||
int rc = syscall(SC_beep, tone);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html
|
||||
int fsync(int fd)
|
||||
{
|
||||
|
|
|
@ -36,7 +36,6 @@ int get_process_name(char* buffer, int buffer_size);
|
|||
int set_process_name(char const* name, size_t name_length);
|
||||
void dump_backtrace(void);
|
||||
int fsync(int fd);
|
||||
int sysbeep(int tone);
|
||||
int gettid(void);
|
||||
int getpagesize(void);
|
||||
pid_t fork(void);
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
|
||||
#include <AK/DeprecatedString.h>
|
||||
#include <AK/FixedArray.h>
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <AK/ScopedValueRollback.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <Kernel/API/BeepInstruction.h>
|
||||
#include <LibCore/SessionManagement.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <limits.h>
|
||||
|
@ -147,11 +149,13 @@ namespace Core::System {
|
|||
|
||||
#ifdef AK_OS_SERENITY
|
||||
|
||||
ErrorOr<void> beep(Optional<size_t> tone)
|
||||
ErrorOr<void> beep(u16 tone)
|
||||
{
|
||||
auto rc = ::sysbeep(tone.value_or(440));
|
||||
if (rc < 0)
|
||||
return Error::from_syscall("beep"sv, -errno);
|
||||
static Optional<int> beep_fd;
|
||||
if (!beep_fd.has_value())
|
||||
beep_fd = TRY(Core::System::open("/dev/beep"sv, O_RDWR));
|
||||
BeepInstruction instruction { tone };
|
||||
TRY(Core::System::write(beep_fd.value(), Span<u8 const>(&instruction, sizeof(BeepInstruction))));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
namespace Core::System {
|
||||
|
||||
#ifdef AK_OS_SERENITY
|
||||
ErrorOr<void> beep(Optional<size_t> tone);
|
||||
ErrorOr<void> beep(u16 tone = 440);
|
||||
ErrorOr<void> pledge(StringView promises, StringView execpromises = {});
|
||||
ErrorOr<void> unveil(StringView path, StringView permissions);
|
||||
ErrorOr<void> unveil_after_exec(StringView path, StringView permissions);
|
||||
|
|
|
@ -1069,7 +1069,7 @@ void TerminalWidget::beep()
|
|||
return;
|
||||
}
|
||||
if (m_bell_mode == BellMode::AudibleBeep) {
|
||||
sysbeep(440);
|
||||
[[maybe_unused]] auto ret_val = Core::System::beep();
|
||||
return;
|
||||
}
|
||||
m_visual_beep_timer->restart(200);
|
||||
|
|
|
@ -194,6 +194,7 @@ struct PluggableOnceCharacterDeviceNodeMatch {
|
|||
};
|
||||
|
||||
static constexpr PluggableOnceCharacterDeviceNodeMatch s_simple_matchers[] = {
|
||||
{ "/dev/beep"sv, 0666, 1, 10 },
|
||||
{ "/dev/kcov"sv, 0666, 30, 0 },
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,6 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
Core::ArgsParser args_parser;
|
||||
args_parser.add_option(tone, "Beep tone", "beep-tone", 'f', "Beep tone (frequency in Hz)");
|
||||
args_parser.parse(arguments);
|
||||
TRY(Core::System::beep(tone));
|
||||
TRY(Core::System::beep(tone.value_or(440)));
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue