Serenity Operating System
at master 78 lines 4.2 kB view raw
1/* 2 * Copyright (c) 2022, Jesse Buhagiar <jesse.buhagiar@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/FixedArray.h> 8#include <Kernel/Bus/USB/USBClasses.h> 9#include <Kernel/Bus/USB/USBConfiguration.h> 10#include <Kernel/Bus/USB/USBInterface.h> 11#include <Kernel/Bus/USB/USBRequest.h> 12#include <Kernel/StdLib.h> 13 14namespace Kernel::USB { 15 16ErrorOr<void> USBConfiguration::enumerate_interfaces() 17{ 18 auto descriptor_hierarchy_buffer = TRY(FixedArray<u8>::create(m_descriptor.total_length)); // Buffer for us to store the entire hierarchy into 19 20 // The USB spec is a little bit janky here... Interface and Endpoint descriptors aren't fetched 21 // through a `GET_DESCRIPTOR` request to the device. Instead, the _entire_ hierarchy is returned 22 // to us in one go. 23 auto transfer_length = TRY(m_device.control_transfer(USB_REQUEST_TRANSFER_DIRECTION_DEVICE_TO_HOST, USB_REQUEST_GET_DESCRIPTOR, (DESCRIPTOR_TYPE_CONFIGURATION << 8), 0, m_descriptor.total_length, descriptor_hierarchy_buffer.data())); 24 25 // FIXME: Why does transfer length return the actual size +8 bytes? 26 if (transfer_length < m_descriptor.total_length) 27 return EIO; 28 29 u8* interface_descriptors_base = descriptor_hierarchy_buffer.data() + sizeof(USBConfigurationDescriptor); 30 USBInterfaceDescriptor* interface_descriptor = reinterpret_cast<USBInterfaceDescriptor*>(interface_descriptors_base); 31 Vector<USBEndpointDescriptor> endpoint_descriptors; 32 for (auto interface = 0u; interface < m_descriptor.number_of_interfaces; interface++) { 33 endpoint_descriptors.ensure_capacity(interface_descriptor->number_of_endpoints); 34 35 if constexpr (USB_DEBUG) { 36 dbgln("Interface Descriptor {}", interface); 37 dbgln("interface_id: {:02x}", interface_descriptor->interface_id); 38 dbgln("alternate_setting: {:02x}", interface_descriptor->alternate_setting); 39 dbgln("number_of_endpoints: {:02x}", interface_descriptor->number_of_endpoints); 40 dbgln("interface_class_code: {:02x}", interface_descriptor->interface_class_code); 41 dbgln("interface_sub_class_code: {:02x}", interface_descriptor->interface_sub_class_code); 42 dbgln("interface_protocol: {:02x}", interface_descriptor->interface_protocol); 43 dbgln("interface_string_descriptor_index: {}", interface_descriptor->interface_string_descriptor_index); 44 } 45 46 // Get all the endpoint descriptors 47 for (auto endpoint = 0u; endpoint < interface_descriptor->number_of_endpoints; endpoint++) { 48 u8* raw_endpoint_descriptor_offset = interface_descriptors_base + sizeof(USBInterfaceDescriptor) + (endpoint * sizeof(USBEndpointDescriptor)); 49 50 // FIXME: It looks like HID descriptors come BEFORE the endpoint descriptors for a HID device, so we should load 51 // these too eventually. 52 // See here: https://www.usb.org/defined-class-codes 53 if (interface_descriptor->interface_class_code == USB_CLASS_HID) 54 raw_endpoint_descriptor_offset += sizeof(USBHIDDescriptor); // Skip the HID descriptor (this was worked out via buffer inspection) 55 56 USBEndpointDescriptor endpoint_descriptor; 57 memcpy(&endpoint_descriptor, raw_endpoint_descriptor_offset, sizeof(USBEndpointDescriptor)); 58 59 if constexpr (USB_DEBUG) { 60 dbgln("Endpoint Descriptor {}", endpoint); 61 dbgln("Endpoint Address: {}", endpoint_descriptor.endpoint_address); 62 dbgln("Endpoint Attribute Bitmap: {:08b}", endpoint_descriptor.endpoint_attributes_bitmap); 63 dbgln("Endpoint Maximum Packet Size: {}", endpoint_descriptor.max_packet_size); 64 dbgln("Endpoint Poll Interval (in frames): {}", endpoint_descriptor.poll_interval_in_frames); 65 } 66 67 endpoint_descriptors.append(endpoint_descriptor); 68 } 69 70 USBInterface device_interface(*this, *interface_descriptor, endpoint_descriptors); 71 m_interfaces.append(device_interface); 72 interface_descriptor += interface_descriptor->number_of_endpoints * sizeof(USBEndpointDescriptor); 73 } 74 75 return {}; 76} 77 78}