mirror of
https://github.com/RGBCube/serenity
synced 2025-05-22 17:25:07 +00:00
Kernel: Add /proc/bus/usb to store information about connected devices
This commit is contained in:
parent
71c9572e74
commit
f2ff55dd09
1 changed files with 95 additions and 1 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue