PCSpeakerDevice.cpp 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /*
  2. * Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/API/BeepInstruction.h>
  7. #if ARCH(X86_64)
  8. # include <Kernel/Arch/x86_64/PCSpeaker.h>
  9. #endif
  10. #include <Kernel/Boot/CommandLine.h>
  11. #include <Kernel/Devices/DeviceManagement.h>
  12. #include <Kernel/Devices/Generic/PCSpeakerDevice.h>
  13. #include <Kernel/Sections.h>
  14. namespace Kernel {
  15. UNMAP_AFTER_INIT NonnullRefPtr<PCSpeakerDevice> PCSpeakerDevice::must_create()
  16. {
  17. auto device = MUST(DeviceManagement::try_create_device<PCSpeakerDevice>());
  18. return *device;
  19. }
  20. UNMAP_AFTER_INIT PCSpeakerDevice::PCSpeakerDevice()
  21. : CharacterDevice(1, 10)
  22. {
  23. }
  24. UNMAP_AFTER_INIT PCSpeakerDevice::~PCSpeakerDevice() = default;
  25. bool PCSpeakerDevice::can_read(OpenFileDescription const&, u64) const
  26. {
  27. return true;
  28. }
  29. ErrorOr<size_t> PCSpeakerDevice::read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t)
  30. {
  31. return Error::from_errno(ENOTIMPL);
  32. }
  33. ErrorOr<size_t> PCSpeakerDevice::write(OpenFileDescription&, u64, UserOrKernelBuffer const& buffer, size_t buffer_size)
  34. {
  35. if (!kernel_command_line().is_pc_speaker_enabled())
  36. return Error::from_errno(ENOTSUP);
  37. if (buffer_size % sizeof(BeepInstruction) != 0)
  38. return Error::from_errno(EINVAL);
  39. BeepInstruction instruction {};
  40. TRY(buffer.read(&instruction, sizeof(BeepInstruction)));
  41. if (instruction.tone < 20 || instruction.tone > 20000)
  42. return Error::from_errno(EINVAL);
  43. if (instruction.milliseconds_duration == 0)
  44. return Error::from_errno(EINVAL);
  45. #if ARCH(X86_64)
  46. PCSpeaker::tone_on(instruction.tone);
  47. auto result = Thread::current()->sleep(Duration::from_milliseconds(instruction.milliseconds_duration));
  48. PCSpeaker::tone_off();
  49. if (result.was_interrupted())
  50. return Error::from_errno(EINTR);
  51. return sizeof(BeepInstruction);
  52. #else
  53. return Error::from_errno(ENOTIMPL);
  54. #endif
  55. }
  56. }