Serenity Operating System
at master 105 lines 3.7 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9// Device is the base class of everything that lives in the /dev directory. 10// 11// To expose a Device to the filesystem, simply pass two unique numbers to the constructor, 12// and then mknod a file in /dev with those numbers. 13// 14// There are two main subclasses: 15// - BlockDevice (random access) 16// - CharacterDevice (sequential) 17#include <AK/DoublyLinkedList.h> 18#include <AK/Error.h> 19#include <AK/Function.h> 20#include <AK/HashMap.h> 21#include <Kernel/Devices/AsyncDeviceRequest.h> 22#include <Kernel/FileSystem/DeviceFileTypes.h> 23#include <Kernel/FileSystem/File.h> 24#include <Kernel/FileSystem/SysFS/Registry.h> 25#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/DeviceComponent.h> 26#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/SymbolicLinkDeviceComponent.h> 27#include <Kernel/Library/LockRefPtr.h> 28#include <Kernel/UnixTypes.h> 29 30namespace Kernel { 31 32class Device : public File { 33protected: 34 enum class State { 35 Normal, 36 BeingRemoved, 37 }; 38 39public: 40 virtual ~Device() override; 41 42 MajorNumber major() const { return m_major; } 43 MinorNumber minor() const { return m_minor; } 44 45 virtual ErrorOr<NonnullOwnPtr<KString>> pseudo_path(OpenFileDescription const&) const override; 46 virtual ErrorOr<NonnullRefPtr<OpenFileDescription>> open(int options) override; 47 48 UserID uid() const { return m_uid; } 49 GroupID gid() const { return m_gid; } 50 51 virtual bool is_device() const override { return true; } 52 virtual void will_be_destroyed() override; 53 virtual ErrorOr<void> after_inserting(); 54 virtual bool is_openable_by_jailed_processes() const { return false; } 55 void process_next_queued_request(Badge<AsyncDeviceRequest>, AsyncDeviceRequest const&); 56 57 template<typename AsyncRequestType, typename... Args> 58 ErrorOr<NonnullLockRefPtr<AsyncRequestType>> try_make_request(Args&&... args) 59 { 60 auto request = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) AsyncRequestType(*this, forward<Args>(args)...))); 61 SpinlockLocker lock(m_requests_lock); 62 bool was_empty = m_requests.is_empty(); 63 TRY(m_requests.try_append(request)); 64 if (was_empty) 65 request->do_start(move(lock)); 66 return request; 67 } 68 69protected: 70 Device(MajorNumber major, MinorNumber minor); 71 void set_uid(UserID uid) { m_uid = uid; } 72 void set_gid(GroupID gid) { m_gid = gid; } 73 74 void after_inserting_add_to_device_management(); 75 void before_will_be_destroyed_remove_from_device_management(); 76 77 virtual void after_inserting_add_symlink_to_device_identifier_directory() = 0; 78 virtual void before_will_be_destroyed_remove_symlink_from_device_identifier_directory() = 0; 79 80 // FIXME: These methods will be eventually removed after all nodes in /sys/dev/block/ and 81 // /sys/dev/char/ are symlinks. 82 virtual void after_inserting_add_to_device_identifier_directory() = 0; 83 virtual void before_will_be_destroyed_remove_from_device_identifier_directory() = 0; 84 85private: 86 MajorNumber const m_major { 0 }; 87 MinorNumber const m_minor { 0 }; 88 UserID m_uid { 0 }; 89 GroupID m_gid { 0 }; 90 91 State m_state { State::Normal }; 92 93 Spinlock<LockRank::None> m_requests_lock {}; 94 DoublyLinkedList<LockRefPtr<AsyncDeviceRequest>> m_requests; 95 96protected: 97 // FIXME: This pointer will be eventually removed after all nodes in /sys/dev/block/ and 98 // /sys/dev/char/ are symlinks. 99 LockRefPtr<SysFSDeviceComponent> m_sysfs_component; 100 101 LockRefPtr<SysFSSymbolicLinkDeviceComponent> m_symlink_sysfs_component; 102 LockRefPtr<SysFSDirectory> m_sysfs_device_directory; 103}; 104 105}