Device.h 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. // Device is the base class of everything that lives in the /dev directory.
  8. //
  9. // To expose a Device to the filesystem, simply pass two unique numbers to the constructor,
  10. // and then mknod a file in /dev with those numbers.
  11. //
  12. // There are two main subclasses:
  13. // - BlockDevice (random access)
  14. // - CharacterDevice (sequential)
  15. #include <AK/DoublyLinkedList.h>
  16. #include <AK/Function.h>
  17. #include <AK/HashMap.h>
  18. #include <Kernel/Devices/AsyncDeviceRequest.h>
  19. #include <Kernel/FileSystem/File.h>
  20. #include <Kernel/Locking/Mutex.h>
  21. #include <Kernel/UnixTypes.h>
  22. namespace Kernel {
  23. class Device : public File {
  24. public:
  25. virtual ~Device() override;
  26. unsigned major() const { return m_major; }
  27. unsigned minor() const { return m_minor; }
  28. virtual String absolute_path(const FileDescription&) const override;
  29. virtual String absolute_path() const;
  30. UserID uid() const { return m_uid; }
  31. GroupID gid() const { return m_gid; }
  32. virtual mode_t required_mode() const = 0;
  33. virtual String device_name() const = 0;
  34. virtual bool is_device() const override { return true; }
  35. static void for_each(Function<void(Device&)>);
  36. static Device* get_device(unsigned major, unsigned minor);
  37. void process_next_queued_request(Badge<AsyncDeviceRequest>, const AsyncDeviceRequest&);
  38. template<typename AsyncRequestType, typename... Args>
  39. NonnullRefPtr<AsyncRequestType> make_request(Args&&... args)
  40. {
  41. auto request = adopt_ref(*new AsyncRequestType(*this, forward<Args>(args)...));
  42. SpinlockLocker lock(m_requests_lock);
  43. bool was_empty = m_requests.is_empty();
  44. m_requests.append(request);
  45. if (was_empty)
  46. request->do_start(move(lock));
  47. return request;
  48. }
  49. protected:
  50. Device(unsigned major, unsigned minor);
  51. void set_uid(UserID uid) { m_uid = uid; }
  52. void set_gid(GroupID gid) { m_gid = gid; }
  53. static HashMap<u32, Device*>& all_devices();
  54. private:
  55. unsigned m_major { 0 };
  56. unsigned m_minor { 0 };
  57. UserID m_uid { 0 };
  58. GroupID m_gid { 0 };
  59. Spinlock<u8> m_requests_lock;
  60. DoublyLinkedList<RefPtr<AsyncDeviceRequest>> m_requests;
  61. };
  62. }