diff options
author | Jesse Buhagiar <jooster669@gmail.com> | 2021-06-09 00:14:21 +1000 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-06-18 17:04:57 +0430 |
commit | f2ff55dd09c266e341c7172ed9fa6d4e142a48d9 (patch) | |
tree | 62c4bc2e95557a3a90505f59dbba8a918c8c8c1a /Kernel/FileSystem | |
parent | 71c9572e744a8d11b03347d97558cb8f57eb1e69 (diff) | |
download | serenity-f2ff55dd09c266e341c7172ed9fa6d4e142a48d9.zip |
Kernel: Add /proc/bus/usb to store information about connected devices
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r-- | Kernel/FileSystem/ProcFS.cpp | 96 |
1 files changed, 95 insertions, 1 deletions
diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 0bc78c51fe..17120354dd 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -18,6 +18,8 @@ #include <Kernel/Debug.h> #include <Kernel/Devices/BlockDevice.h> #include <Kernel/Devices/HID/HIDManagement.h> +#include <Kernel/Devices/USB/UHCIController.h> +#include <Kernel/Devices/USB/USBDevice.h> #include <Kernel/FileSystem/Custody.h> #include <Kernel/FileSystem/FileBackedFileSystem.h> #include <Kernel/FileSystem/FileDescription.h> @@ -49,6 +51,8 @@ namespace Kernel { enum ProcParentDirectory { PDI_AbstractRoot = 0, PDI_Root, + PDI_Root_bus, + PDI_Root_bus_usb, PDI_Root_sys, PDI_Root_net, PDI_PID, @@ -81,6 +85,7 @@ enum ProcFileType { FI_Root_self, // symlink FI_Root_sys, // directory FI_Root_net, // directory + FI_Root_bus, // directory __FI_Root_End, FI_Root_sys_variable, @@ -91,6 +96,9 @@ enum ProcFileType { FI_Root_net_udp, FI_Root_net_local, + FI_Root_bus_usb, + FI_Root_bus_usb_device, + FI_PID, __FI_PID_Start, @@ -142,6 +150,13 @@ static inline size_t to_sys_index(const InodeIdentifier& identifier) return identifier.index().value() >> 16u; } +static inline u8 to_usb_device_address(const InodeIdentifier& identifier) +{ + VERIFY(to_proc_parent_directory(identifier) == PDI_Root_bus_usb); + VERIFY(to_proc_file_type(identifier) == FI_Root_bus_usb_device); + return (identifier.index().value() >> 16u) & 0xff; +} + static inline InodeIdentifier to_identifier(unsigned fsid, ProcParentDirectory parent, ProcessID pid, ProcFileType proc_file_type) { return { fsid, ((unsigned)parent << 12u) | ((unsigned)pid.value() << 16u) | (unsigned)proc_file_type }; @@ -163,6 +178,12 @@ static inline InodeIdentifier sys_var_to_identifier(unsigned fsid, unsigned inde return { fsid, (PDI_Root_sys << 12u) | (index << 16u) | FI_Root_sys_variable }; } +static inline InodeIdentifier usb_device_address_to_identifier(unsigned fsid, unsigned device_address) +{ + VERIFY(device_address < 127); + return { fsid, (PDI_Root_bus_usb << 12u) | (device_address << 16u) | FI_Root_bus_usb_device }; +} + static inline InodeIdentifier to_parent_id(const InodeIdentifier& identifier) { switch (to_proc_parent_directory(identifier)) { @@ -173,6 +194,10 @@ static inline InodeIdentifier to_parent_id(const InodeIdentifier& identifier) return { identifier.fsid(), FI_Root_sys }; case PDI_Root_net: return { identifier.fsid(), FI_Root_net }; + case PDI_Root_bus: + return { identifier.fsid(), FI_Root_bus }; + case PDI_Root_bus_usb: + return to_identifier(identifier.fsid(), PDI_Root_bus, to_pid(identifier), FI_Root_bus_usb); case PDI_PID: return to_identifier(identifier.fsid(), PDI_Root, to_pid(identifier), FI_PID); case PDI_PID_fd: @@ -217,6 +242,8 @@ static inline bool is_directory(const InodeIdentifier& identifier) case FI_Root: case FI_Root_sys: case FI_Root_net: + case FI_Root_bus: + case FI_Root_bus_usb: case FI_PID: case FI_PID_fd: case FI_PID_stacks: @@ -534,6 +561,33 @@ static bool procfs$net_tcp(InodeIdentifier, KBufferBuilder& builder) return true; } +static bool procfs$usb_entry(InodeIdentifier identifier, KBufferBuilder& builder) +{ + u8 dev_id = to_usb_device_address(identifier); + auto const& device = USB::UHCIController::the().get_device_from_address(dev_id); + VERIFY(device); // Something has gone very wrong if this isn't true + + JsonArraySerializer array { builder }; + + auto obj = array.add_object(); + obj.add("usb_spec_compliance_bcd", device->device_descriptor().usb_spec_compliance_bcd); + obj.add("device_class", device->device_descriptor().device_class); + obj.add("device_sub_class", device->device_descriptor().device_sub_class); + obj.add("device_protocol", device->device_descriptor().device_protocol); + obj.add("max_packet_size", device->device_descriptor().max_packet_size); + obj.add("vendor_id", device->device_descriptor().vendor_id); + obj.add("product_id", device->device_descriptor().product_id); + obj.add("device_release_bcd", device->device_descriptor().device_release_bcd); + obj.add("manufacturer_id_descriptor_index", device->device_descriptor().manufacturer_id_descriptor_index); + obj.add("product_string_descriptor_index", device->device_descriptor().product_string_descriptor_index); + obj.add("serial_number_descriptor_index", device->device_descriptor().serial_number_descriptor_index); + obj.add("num_configurations", device->device_descriptor().num_configurations); + obj.finish(); + array.finish(); + + return true; +} + static bool procfs$net_udp(InodeIdentifier, KBufferBuilder& builder) { JsonArraySerializer array { builder }; @@ -1074,6 +1128,7 @@ KResult ProcFSInode::refresh_data(FileDescription& description) const auto* directory_entry = fs().get_directory_entry(identifier()); bool (*read_callback)(InodeIdentifier, KBufferBuilder&) = nullptr; + if (directory_entry) { read_callback = directory_entry->read_callback; VERIFY(read_callback); @@ -1097,6 +1152,9 @@ KResult ProcFSInode::refresh_data(FileDescription& description) const break; } break; + case PDI_Root_bus_usb: + read_callback = procfs$usb_entry; + break; default: VERIFY_NOT_REACHED(); } @@ -1181,6 +1239,11 @@ InodeMetadata ProcFSInode::metadata() const return metadata; } + if (proc_parent_directory == PDI_Root_bus_usb) { + metadata.mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + return metadata; + } + switch (proc_file_type) { case FI_Root_self: metadata.mode = S_IFLNK | S_IRUSR | S_IRGRP | S_IROTH; @@ -1193,6 +1256,8 @@ InodeMetadata ProcFSInode::metadata() const case FI_Root: case FI_Root_sys: case FI_Root_net: + case FI_Root_bus: + case FI_Root_bus_usb: metadata.mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; break; case FI_PID: @@ -1335,6 +1400,24 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr }); } break; + case FI_Root_bus: { + callback({ "usb", to_identifier(fsid(), PDI_Root_bus, 0, FI_Root_bus_usb), 0 }); + break; + } + + case FI_Root_bus_usb: { + // FIXME: We currently only support 2 USB devices due to UHCI only... The controller stack should be modified + // to support any number of devices (this is a gross hack....) + for (auto port = 0; port < 2; port++) { + auto const& device = USB::UHCIController::the().get_device_at_port(static_cast<USB::Device::PortNumber>(port)); + if (device == nullptr) + continue; + + callback({ String::number(device->address()), usb_device_address_to_identifier(fsid(), device->address()), 0 }); + } + break; + } + default: return KSuccess; } @@ -1416,6 +1499,16 @@ RefPtr<Inode> ProcFSInode::lookup(StringView name) return {}; } + if (proc_file_type == FI_Root_bus) { + if (name == "usb") + return fs().get_inode(to_identifier(fsid(), PDI_Root_bus, 0, FI_Root_bus_usb)); + } + + if (proc_file_type == FI_Root_bus_usb) { + u8 device_address = name.to_uint().value(); + return fs().get_inode(usb_device_address_to_identifier(fsid(), device_address)); + } + if (proc_file_type == FI_PID_fd) { auto name_as_number = name.to_uint(); if (!name_as_number.has_value()) @@ -1705,6 +1798,7 @@ ProcFS::ProcFS() m_entries[FI_Root_profile] = { "profile", FI_Root_profile, true, procfs$profile }; m_entries[FI_Root_sys] = { "sys", FI_Root_sys, true }; m_entries[FI_Root_net] = { "net", FI_Root_net, false }; + m_entries[FI_Root_bus] = { "bus", FI_Root_bus, false }; m_entries[FI_Root_net_adapters] = { "adapters", FI_Root_net_adapters, false, procfs$net_adapters }; m_entries[FI_Root_net_arp] = { "arp", FI_Root_net_arp, true, procfs$net_arp }; @@ -1726,7 +1820,7 @@ ProcFS::ProcFS() ProcFS::ProcFSDirectoryEntry* ProcFS::get_directory_entry(InodeIdentifier identifier) const { auto proc_file_type = to_proc_file_type(identifier); - if (proc_file_type != FI_Invalid && proc_file_type != FI_Root_sys_variable && proc_file_type < FI_MaxStaticFileIndex) + if (proc_file_type != FI_Invalid && proc_file_type != FI_Root_sys_variable && proc_file_type != FI_Root_bus_usb_device && proc_file_type < FI_MaxStaticFileIndex) return const_cast<ProcFSDirectoryEntry*>(&m_entries[proc_file_type]); return nullptr; } |