From 872c75ac44fa5703023d235384250b7c50d332b2 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 14 Aug 2021 04:31:00 +0100 Subject: [PATCH] Kernel/USB: Split SysFS code into its own file This makes it controller agnostic and allows us to access it from the USB hub code. The copyright says "Liav A." because git blame says he wrote this. --- Kernel/Bus/USB/SysFSUSB.cpp | 127 +++++++++++++++++++++++++ Kernel/Bus/USB/SysFSUSB.h | 52 +++++++++++ Kernel/Bus/USB/UHCIController.cpp | 150 ------------------------------ Kernel/Bus/USB/USBManagement.cpp | 7 ++ Kernel/CMakeLists.txt | 1 + 5 files changed, 187 insertions(+), 150 deletions(-) create mode 100644 Kernel/Bus/USB/SysFSUSB.cpp create mode 100644 Kernel/Bus/USB/SysFSUSB.h diff --git a/Kernel/Bus/USB/SysFSUSB.cpp b/Kernel/Bus/USB/SysFSUSB.cpp new file mode 100644 index 0000000000..5ecc0c5be3 --- /dev/null +++ b/Kernel/Bus/USB/SysFSUSB.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Kernel::USB { + +static SysFSUSBBusDirectory* s_procfs_usb_bus_directory; + +SysFSUSBDeviceInformation::SysFSUSBDeviceInformation(USB::Device& device) + : SysFSComponent(String::number(device.address())) + , m_device(device) +{ +} + +SysFSUSBDeviceInformation::~SysFSUSBDeviceInformation() +{ +} + +KResultOr SysFSUSBDeviceInformation::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription*) const +{ + KBufferBuilder builder; + JsonArraySerializer array { builder }; + + auto obj = array.add_object(); + obj.add("usb_spec_compliance_bcd", m_device->device_descriptor().usb_spec_compliance_bcd); + obj.add("device_class", m_device->device_descriptor().device_class); + obj.add("device_sub_class", m_device->device_descriptor().device_sub_class); + obj.add("device_protocol", m_device->device_descriptor().device_protocol); + obj.add("max_packet_size", m_device->device_descriptor().max_packet_size); + obj.add("vendor_id", m_device->device_descriptor().vendor_id); + obj.add("product_id", m_device->device_descriptor().product_id); + obj.add("device_release_bcd", m_device->device_descriptor().device_release_bcd); + obj.add("manufacturer_id_descriptor_index", m_device->device_descriptor().manufacturer_id_descriptor_index); + obj.add("product_string_descriptor_index", m_device->device_descriptor().product_string_descriptor_index); + obj.add("serial_number_descriptor_index", m_device->device_descriptor().serial_number_descriptor_index); + obj.add("num_configurations", m_device->device_descriptor().num_configurations); + obj.finish(); + array.finish(); + + auto data = builder.build(); + if (!data) + return ENOMEM; + + ssize_t nread = min(static_cast(data->size() - offset), static_cast(count)); + if (!buffer.write(data->data() + offset, nread)) + return EFAULT; + + return nread; +} + +KResult SysFSUSBBusDirectory::traverse_as_directory(unsigned fsid, Function callback) const +{ + ScopedSpinLock lock(m_lock); + // Note: if the parent directory is null, it means something bad happened as this should not happen for the USB directory. + VERIFY(m_parent_directory); + callback({ ".", { fsid, component_index() }, 0 }); + callback({ "..", { fsid, m_parent_directory->component_index() }, 0 }); + + for (auto& device_node : m_device_nodes) { + InodeIdentifier identifier = { fsid, device_node.component_index() }; + callback({ device_node.name(), identifier, 0 }); + } + return KSuccess; +} + +RefPtr SysFSUSBBusDirectory::lookup(StringView name) +{ + ScopedSpinLock lock(m_lock); + for (auto& device_node : m_device_nodes) { + if (device_node.name() == name) { + return device_node; + } + } + return {}; +} + +RefPtr SysFSUSBBusDirectory::device_node_for(USB::Device& device) +{ + RefPtr checked_device = device; + for (auto& device_node : m_device_nodes) { + if (device_node.device().ptr() == checked_device.ptr()) + return device_node; + } + return {}; +} + +void SysFSUSBBusDirectory::plug(USB::Device& new_device) +{ + ScopedSpinLock lock(m_lock); + auto device_node = device_node_for(new_device); + VERIFY(!device_node); + m_device_nodes.append(SysFSUSBDeviceInformation::create(new_device)); +} + +void SysFSUSBBusDirectory::unplug(USB::Device& deleted_device) +{ + ScopedSpinLock lock(m_lock); + auto device_node = device_node_for(deleted_device); + VERIFY(device_node); + device_node->m_list_node.remove(); +} + +UNMAP_AFTER_INIT SysFSUSBBusDirectory::SysFSUSBBusDirectory(SysFSBusDirectory& buses_directory) + : SysFSDirectory("usb"sv, buses_directory) +{ +} + +UNMAP_AFTER_INIT void SysFSUSBBusDirectory::initialize() +{ + auto directory = adopt_ref(*new SysFSUSBBusDirectory(SysFSComponentRegistry::the().buses_directory())); + SysFSComponentRegistry::the().register_new_bus_directory(directory); + s_procfs_usb_bus_directory = directory; +} + +NonnullRefPtr SysFSUSBDeviceInformation::create(USB::Device& device) +{ + return adopt_ref(*new SysFSUSBDeviceInformation(device)); +} + +} diff --git a/Kernel/Bus/USB/SysFSUSB.h b/Kernel/Bus/USB/SysFSUSB.h new file mode 100644 index 0000000000..6c59b6a2de --- /dev/null +++ b/Kernel/Bus/USB/SysFSUSB.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel::USB { + +class SysFSUSBDeviceInformation : public SysFSComponent { + friend class SysFSUSBBusDirectory; + +public: + virtual ~SysFSUSBDeviceInformation() override; + + static NonnullRefPtr create(USB::Device&); + + RefPtr device() const { return m_device; } + +protected: + explicit SysFSUSBDeviceInformation(USB::Device& device); + + virtual KResultOr read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription*) const override; + + IntrusiveListNode> m_list_node; + + NonnullRefPtr m_device; +}; + +class SysFSUSBBusDirectory final : public SysFSDirectory { +public: + static void initialize(); + void plug(USB::Device&); + void unplug(USB::Device&); + + virtual KResult traverse_as_directory(unsigned, Function) const override; + virtual RefPtr lookup(StringView name) override; + +private: + explicit SysFSUSBBusDirectory(SysFSBusDirectory&); + + RefPtr device_node_for(USB::Device& device); + + IntrusiveList, &SysFSUSBDeviceInformation::m_list_node> m_device_nodes; + mutable SpinLock m_lock; +}; + +} diff --git a/Kernel/Bus/USB/UHCIController.cpp b/Kernel/Bus/USB/UHCIController.cpp index fbae95bac5..63e668a92f 100644 --- a/Kernel/Bus/USB/UHCIController.cpp +++ b/Kernel/Bus/USB/UHCIController.cpp @@ -5,15 +5,11 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include #include #include #include #include #include -#include -#include #include #include #include @@ -68,148 +64,6 @@ static constexpr u16 UCHI_PORTSC_NON_WRITE_CLEAR_BIT_MASK = 0x1FF5; // This is u static constexpr u8 UHCI_NUMBER_OF_ISOCHRONOUS_TDS = 128; static constexpr u16 UHCI_NUMBER_OF_FRAMES = 1024; -class SysFSUSBBusDirectory; -static SysFSUSBBusDirectory* s_procfs_usb_bus_directory; - -class SysFSUSBDeviceInformation : public SysFSComponent { - friend class SysFSUSBBusDirectory; - -public: - virtual ~SysFSUSBDeviceInformation() override {}; - - static NonnullRefPtr create(USB::Device&); - - RefPtr device() const { return m_device; } - -protected: - explicit SysFSUSBDeviceInformation(USB::Device& device) - : SysFSComponent(String::number(device.address())) - , m_device(device) - { - } - - virtual KResultOr read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription*) const override - { - KBufferBuilder builder; - JsonArraySerializer array { builder }; - - auto obj = array.add_object(); - obj.add("usb_spec_compliance_bcd", m_device->device_descriptor().usb_spec_compliance_bcd); - obj.add("device_class", m_device->device_descriptor().device_class); - obj.add("device_sub_class", m_device->device_descriptor().device_sub_class); - obj.add("device_protocol", m_device->device_descriptor().device_protocol); - obj.add("max_packet_size", m_device->device_descriptor().max_packet_size); - obj.add("vendor_id", m_device->device_descriptor().vendor_id); - obj.add("product_id", m_device->device_descriptor().product_id); - obj.add("device_release_bcd", m_device->device_descriptor().device_release_bcd); - obj.add("manufacturer_id_descriptor_index", m_device->device_descriptor().manufacturer_id_descriptor_index); - obj.add("product_string_descriptor_index", m_device->device_descriptor().product_string_descriptor_index); - obj.add("serial_number_descriptor_index", m_device->device_descriptor().serial_number_descriptor_index); - obj.add("num_configurations", m_device->device_descriptor().num_configurations); - obj.finish(); - array.finish(); - - auto data = builder.build(); - if (!data) - return ENOMEM; - - ssize_t nread = min(static_cast(data->size() - offset), static_cast(count)); - if (!buffer.write(data->data() + offset, nread)) - return EFAULT; - - return nread; - } - IntrusiveListNode> m_list_node; - - NonnullRefPtr m_device; -}; - -class SysFSUSBBusDirectory final : public SysFSDirectory { -public: - static void initialize(); - void plug(USB::Device&); - void unplug(USB::Device&); - - virtual KResult traverse_as_directory(unsigned, Function) const override; - virtual RefPtr lookup(StringView name) override; - -private: - explicit SysFSUSBBusDirectory(SysFSBusDirectory&); - - RefPtr device_node_for(USB::Device& device); - - IntrusiveList, &SysFSUSBDeviceInformation::m_list_node> m_device_nodes; - mutable SpinLock m_lock; -}; - -KResult SysFSUSBBusDirectory::traverse_as_directory(unsigned fsid, Function callback) const -{ - ScopedSpinLock lock(m_lock); - // Note: if the parent directory is null, it means something bad happened as this should not happen for the USB directory. - VERIFY(m_parent_directory); - callback({ ".", { fsid, component_index() }, 0 }); - callback({ "..", { fsid, m_parent_directory->component_index() }, 0 }); - - for (auto& device_node : m_device_nodes) { - InodeIdentifier identifier = { fsid, device_node.component_index() }; - callback({ device_node.name(), identifier, 0 }); - } - return KSuccess; -} -RefPtr SysFSUSBBusDirectory::lookup(StringView name) -{ - ScopedSpinLock lock(m_lock); - for (auto& device_node : m_device_nodes) { - if (device_node.name() == name) { - return device_node; - } - } - return {}; -} - -RefPtr SysFSUSBBusDirectory::device_node_for(USB::Device& device) -{ - RefPtr checked_device = device; - for (auto& device_node : m_device_nodes) { - if (device_node.device().ptr() == checked_device.ptr()) - return device_node; - } - return {}; -} - -void SysFSUSBBusDirectory::plug(USB::Device& new_device) -{ - ScopedSpinLock lock(m_lock); - auto device_node = device_node_for(new_device); - VERIFY(!device_node); - m_device_nodes.append(SysFSUSBDeviceInformation::create(new_device)); -} - -void SysFSUSBBusDirectory::unplug(USB::Device& deleted_device) -{ - ScopedSpinLock lock(m_lock); - auto device_node = device_node_for(deleted_device); - VERIFY(device_node); - device_node->m_list_node.remove(); -} - -UNMAP_AFTER_INIT SysFSUSBBusDirectory::SysFSUSBBusDirectory(SysFSBusDirectory& buses_directory) - : SysFSDirectory("usb"sv, buses_directory) -{ -} - -UNMAP_AFTER_INIT void SysFSUSBBusDirectory::initialize() -{ - auto directory = adopt_ref(*new SysFSUSBBusDirectory(SysFSComponentRegistry::the().buses_directory())); - SysFSComponentRegistry::the().register_new_bus_directory(directory); - s_procfs_usb_bus_directory = directory; -} - -NonnullRefPtr SysFSUSBDeviceInformation::create(USB::Device& device) -{ - return adopt_ref(*new SysFSUSBDeviceInformation(device)); -} - KResultOr> UHCIController::try_to_initialize(PCI::Address address) { // NOTE: This assumes that address is pointing to a valid UHCI controller. @@ -226,10 +80,6 @@ KResultOr> UHCIController::try_to_initialize(PCI:: KResult UHCIController::initialize() { - // FIXME: We create the /proc/bus/usb representation here, but it should really be handled - // in a more broad singleton than this once we refactor things in USB subsystem. - SysFSUSBBusDirectory::initialize(); - dmesgln("UHCI: Controller found {} @ {}", PCI::get_id(pci_address()), pci_address()); dmesgln("UHCI: I/O base {}", m_io_base); dmesgln("UHCI: Interrupt line: {}", PCI::get_interrupt_line(pci_address())); diff --git a/Kernel/Bus/USB/USBManagement.cpp b/Kernel/Bus/USB/USBManagement.cpp index 63dffc2de4..97832c82d0 100644 --- a/Kernel/Bus/USB/USBManagement.cpp +++ b/Kernel/Bus/USB/USBManagement.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -14,6 +15,7 @@ namespace Kernel::USB { static Singleton s_the; +READONLY_AFTER_INIT bool s_initialized_sys_fs_directory = false; UNMAP_AFTER_INIT USBManagement::USBManagement() { @@ -64,6 +66,11 @@ bool USBManagement::initialized() UNMAP_AFTER_INIT void USBManagement::initialize() { + if (!s_initialized_sys_fs_directory) { + USB::SysFSUSBBusDirectory::initialize(); + s_initialized_sys_fs_directory = true; + } + s_the.ensure_instance(); } diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 51b83a6090..4a20358817 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -31,6 +31,7 @@ set(KERNEL_SOURCES Bus/PCI/MMIOAccess.cpp Bus/PCI/Initializer.cpp Bus/PCI/WindowedMMIOAccess.cpp + Bus/USB/SysFSUSB.cpp Bus/USB/UHCIController.cpp Bus/USB/UHCIRootHub.cpp Bus/USB/USBController.cpp