From dac26f89cb4407133d73e1dc6ceae022f3837572 Mon Sep 17 00:00:00 2001 From: Jesse Buhagiar Date: Mon, 11 Apr 2022 20:18:31 +1000 Subject: Kernel/USB: Fetch configuration descriptors on enumeration This also introduces a new class, `USBConfiguration` that stores a configuration. The device, when instructed, sets this configuration and holds a pointer to it so we have a record of what configuration is currently active. --- Kernel/Bus/USB/USBConfiguration.h | 38 ++++++++++++++++++++++++++++++++++++++ Kernel/Bus/USB/USBDevice.cpp | 20 ++++++++++++++++++++ Kernel/Bus/USB/USBDevice.h | 4 ++++ 3 files changed, 62 insertions(+) create mode 100644 Kernel/Bus/USB/USBConfiguration.h (limited to 'Kernel/Bus') diff --git a/Kernel/Bus/USB/USBConfiguration.h b/Kernel/Bus/USB/USBConfiguration.h new file mode 100644 index 0000000000..3fba019ef8 --- /dev/null +++ b/Kernel/Bus/USB/USBConfiguration.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022, Jesse Buhagiar + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Kernel::USB { + +class Device; + +class USBConfiguration { +public: + USBConfiguration() = delete; + USBConfiguration(Device& device, USBConfigurationDescriptor const configuration_descriptor) + : m_device(device) + , m_descriptor(configuration_descriptor) + { + } + + Device const& device() const { return m_device; } + + u8 interface_count() const { return m_descriptor.number_of_interfaces; } + u8 configuration_id() const { return m_descriptor.configuration_value; } + u8 attributes() const { return m_descriptor.attributes_bitmap; } + u16 max_power_ma() const { return m_descriptor.max_power_in_ma * 2u; } // Note: "Power" is used incorrectly here, however it's what it's called in the descriptor/documentation + +private: + Device& m_device; // Reference to the device linked to this configuration + USBConfigurationDescriptor m_descriptor; // Descriptor that backs this configuration +}; + +} diff --git a/Kernel/Bus/USB/USBDevice.cpp b/Kernel/Bus/USB/USBDevice.cpp index 73257b20ea..4e21a3ca69 100644 --- a/Kernel/Bus/USB/USBDevice.cpp +++ b/Kernel/Bus/USB/USBDevice.cpp @@ -115,6 +115,26 @@ ErrorOr Device::enumerate_device() dbgln_if(USB_DEBUG, "USB Device: Set address to {}", m_address); memcpy(&m_device_descriptor, &dev_descriptor, sizeof(USBDeviceDescriptor)); + + // Fetch the configuration descriptors from the device + m_configurations.ensure_capacity(m_device_descriptor.num_configurations); + for (auto configuration = 0u; configuration < m_device_descriptor.num_configurations; configuration++) { + USBConfigurationDescriptor configuration_descriptor; + transfer_length = TRY(m_default_pipe->control_transfer(USB_REQUEST_TRANSFER_DIRECTION_DEVICE_TO_HOST, USB_REQUEST_GET_DESCRIPTOR, (DESCRIPTOR_TYPE_CONFIGURATION << 8u) | configuration, 0, sizeof(USBConfigurationDescriptor), &configuration_descriptor)); + + if constexpr (USB_DEBUG) { + dbgln("USB Configuration Descriptor {}", configuration); + dbgln("Total Length: {}", configuration_descriptor.total_length); + dbgln("Number of interfaces: {}", configuration_descriptor.number_of_interfaces); + dbgln("Configuration Value: {}", configuration_descriptor.configuration_value); + dbgln("Attributes Bitmap: {:08b}", configuration_descriptor.attributes_bitmap); + dbgln("Maximum Power: {}mA", configuration_descriptor.max_power_in_ma * 2u); // This value is in 2mA steps + } + + USBConfiguration device_configuration(*this, configuration_descriptor); + m_configurations.append(device_configuration); + } + return {}; } diff --git a/Kernel/Bus/USB/USBDevice.h b/Kernel/Bus/USB/USBDevice.h index 2ac68482ba..e2a1aac4ff 100644 --- a/Kernel/Bus/USB/USBDevice.h +++ b/Kernel/Bus/USB/USBDevice.h @@ -8,11 +8,14 @@ #include #include +#include +#include #include namespace Kernel::USB { class USBController; +class USBConfiguration; // // Some nice info from FTDI on device enumeration and how some of this @@ -55,6 +58,7 @@ protected: u16 m_vendor_id { 0 }; // This device's vendor ID assigned by the USB group u16 m_product_id { 0 }; // This device's product ID assigned by the USB group USBDeviceDescriptor m_device_descriptor {}; // Device Descriptor obtained from USB Device + Vector m_configurations; // Configurations for this device NonnullRefPtr m_controller; NonnullOwnPtr m_default_pipe; // Default communication pipe (endpoint0) used during enumeration -- cgit v1.2.3