mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 17:31:58 -05:00
Kernel/USB: Create controller base class and introduce USBManagement
This removes Pipes dependency on the UHCIController by introducing a controller base class. This will be used to implement other controllers such as OHCI. Additionally, there can be multiple instances of a UHCI controller. For example, multiple UHCI instances can be required for systems with EHCI controllers. EHCI relies on using multiple of either UHCI or OHCI controllers to drive USB 1.x devices. This means UHCIController can no longer be a singleton. Multiple instances of it can now be created and passed to the device and then to the pipe. To handle finding and creating these instances, USBManagement has been introduced. It has the same pattern as the other management classes such as NetworkManagement.
This commit is contained in:
parent
c5974d3518
commit
7a86a8df90
14 changed files with 261 additions and 74 deletions
|
@ -27,8 +27,6 @@ static constexpr u8 RETRY_COUNTER_RELOAD = 3;
|
|||
|
||||
namespace Kernel::USB {
|
||||
|
||||
static UHCIController* s_the;
|
||||
|
||||
static constexpr u16 UHCI_USBCMD_RUN = 0x0001;
|
||||
static constexpr u16 UHCI_USBCMD_HOST_CONTROLLER_RESET = 0x0002;
|
||||
static constexpr u16 UHCI_USBCMD_GLOBAL_RESET = 0x0004;
|
||||
|
@ -211,43 +209,44 @@ NonnullRefPtr<SysFSUSBDeviceInformation> SysFSUSBDeviceInformation::create(USB::
|
|||
return adopt_ref(*new SysFSUSBDeviceInformation(device));
|
||||
}
|
||||
|
||||
UHCIController& UHCIController::the()
|
||||
KResultOr<NonnullRefPtr<UHCIController>> UHCIController::try_to_initialize(PCI::Address address)
|
||||
{
|
||||
return *s_the;
|
||||
// NOTE: This assumes that address is pointing to a valid UHCI controller.
|
||||
auto controller = adopt_ref_if_nonnull(new (nothrow) UHCIController(address));
|
||||
if (!controller)
|
||||
return ENOMEM;
|
||||
|
||||
auto init_result = controller->initialize();
|
||||
if (init_result.is_error())
|
||||
return init_result;
|
||||
|
||||
return controller.release_nonnull();
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void UHCIController::detect()
|
||||
KResult UHCIController::initialize()
|
||||
{
|
||||
if (kernel_command_line().disable_uhci_controller())
|
||||
return;
|
||||
|
||||
// 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();
|
||||
|
||||
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
|
||||
if (address.is_null())
|
||||
return;
|
||||
|
||||
if (PCI::get_class(address) == 0xc && PCI::get_subclass(address) == 0x03 && PCI::get_programming_interface(address) == 0) {
|
||||
if (!s_the) {
|
||||
s_the = new UHCIController(address, id);
|
||||
s_the->spawn_port_proc();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT UHCIController::UHCIController(PCI::Address address, PCI::ID id)
|
||||
: PCI::Device(address)
|
||||
, m_io_base(PCI::get_BAR4(pci_address()) & ~1)
|
||||
{
|
||||
dmesgln("UHCI: Controller found {} @ {}", id, address);
|
||||
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()));
|
||||
|
||||
reset();
|
||||
start();
|
||||
spawn_port_proc();
|
||||
|
||||
auto reset_result = reset();
|
||||
if (reset_result.is_error())
|
||||
return reset_result;
|
||||
|
||||
auto start_result = start();
|
||||
return start_result;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT UHCIController::UHCIController(PCI::Address address)
|
||||
: PCI::Device(address)
|
||||
, m_io_base(PCI::get_BAR4(pci_address()) & ~1)
|
||||
{
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT UHCIController::~UHCIController()
|
||||
|
@ -275,9 +274,10 @@ RefPtr<USB::Device> const UHCIController::get_device_from_address(u8 device_addr
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void UHCIController::reset()
|
||||
KResult UHCIController::reset()
|
||||
{
|
||||
stop();
|
||||
if (auto stop_result = stop(); stop_result.is_error())
|
||||
return stop_result;
|
||||
|
||||
write_usbcmd(UHCI_USBCMD_HOST_CONTROLLER_RESET);
|
||||
|
||||
|
@ -305,6 +305,8 @@ void UHCIController::reset()
|
|||
// Disable UHCI Controller from raising an IRQ
|
||||
write_usbintr(0);
|
||||
dbgln("UHCI: Reset completed");
|
||||
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void UHCIController::create_structures()
|
||||
|
@ -464,7 +466,7 @@ TransferDescriptor* UHCIController::allocate_transfer_descriptor() const
|
|||
return nullptr; // Huh?! We're outta TDs!!
|
||||
}
|
||||
|
||||
void UHCIController::stop()
|
||||
KResult UHCIController::stop()
|
||||
{
|
||||
write_usbcmd(read_usbcmd() & ~UHCI_USBCMD_RUN);
|
||||
// FIXME: Timeout
|
||||
|
@ -472,9 +474,10 @@ void UHCIController::stop()
|
|||
if (read_usbsts() & UHCI_USBSTS_HOST_CONTROLLER_HALTED)
|
||||
break;
|
||||
}
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
void UHCIController::start()
|
||||
KResult UHCIController::start()
|
||||
{
|
||||
write_usbcmd(read_usbcmd() | UHCI_USBCMD_RUN);
|
||||
// FIXME: Timeout
|
||||
|
@ -483,6 +486,7 @@ void UHCIController::start()
|
|||
break;
|
||||
}
|
||||
dbgln("UHCI: Started");
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
TransferDescriptor* UHCIController::create_transfer_descriptor(Pipe& pipe, PacketID direction, size_t data_len)
|
||||
|
@ -713,7 +717,7 @@ void UHCIController::spawn_port_proc()
|
|||
dbgln("port should be enabled now: {:#04x}\n", read_portsc1());
|
||||
|
||||
USB::Device::DeviceSpeed speed = (port_data & UHCI_PORTSC_LOW_SPEED_DEVICE) ? USB::Device::DeviceSpeed::LowSpeed : USB::Device::DeviceSpeed::FullSpeed;
|
||||
auto device = USB::Device::try_create(USB::Device::PortNumber::Port1, speed);
|
||||
auto device = USB::Device::try_create(*this, USB::Device::PortNumber::Port1, speed);
|
||||
|
||||
if (device.is_error())
|
||||
dmesgln("UHCI: Device creation failed on port 1 ({})", device.error());
|
||||
|
@ -730,7 +734,7 @@ void UHCIController::spawn_port_proc()
|
|||
}
|
||||
}
|
||||
} else {
|
||||
port_data = UHCIController::the().read_portsc2();
|
||||
port_data = read_portsc2();
|
||||
if (port_data & UHCI_PORTSC_CONNECT_STATUS_CHANGED) {
|
||||
if (port_data & UHCI_PORTSC_CURRRENT_CONNECT_STATUS) {
|
||||
dmesgln("UHCI: Device attach detected on Root Port 2");
|
||||
|
@ -751,7 +755,7 @@ void UHCIController::spawn_port_proc()
|
|||
write_portsc2(port_data | UHCI_PORTSC_PORT_ENABLED);
|
||||
dbgln("port should be enabled now: {:#04x}\n", read_portsc2());
|
||||
USB::Device::DeviceSpeed speed = (port_data & UHCI_PORTSC_LOW_SPEED_DEVICE) ? USB::Device::DeviceSpeed::LowSpeed : USB::Device::DeviceSpeed::FullSpeed;
|
||||
auto device = USB::Device::try_create(USB::Device::PortNumber::Port2, speed);
|
||||
auto device = USB::Device::try_create(*this, USB::Device::PortNumber::Port2, speed);
|
||||
|
||||
if (device.is_error())
|
||||
dmesgln("UHCI: Device creation failed on port 2 ({})", device.error());
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <Kernel/Bus/PCI/Device.h>
|
||||
#include <Kernel/Bus/USB/UHCIDescriptorTypes.h>
|
||||
#include <Kernel/Bus/USB/USBDevice.h>
|
||||
#include <Kernel/Bus/USB/USBTransfer.h>
|
||||
#include <Kernel/Bus/USB/USBController.h>
|
||||
#include <Kernel/IO.h>
|
||||
#include <Kernel/Memory/AnonymousVMObject.h>
|
||||
#include <Kernel/Process.h>
|
||||
|
@ -21,30 +20,31 @@
|
|||
|
||||
namespace Kernel::USB {
|
||||
|
||||
class UHCIController final : public PCI::Device {
|
||||
class UHCIController final
|
||||
: public USBController
|
||||
, public PCI::Device {
|
||||
|
||||
public:
|
||||
static void detect();
|
||||
static UHCIController& the();
|
||||
|
||||
static KResultOr<NonnullRefPtr<UHCIController>> try_to_initialize(PCI::Address address);
|
||||
virtual ~UHCIController() override;
|
||||
|
||||
virtual StringView purpose() const override { return "UHCI"; }
|
||||
|
||||
void reset();
|
||||
void stop();
|
||||
void start();
|
||||
virtual KResult initialize() override;
|
||||
virtual KResult reset() override;
|
||||
virtual KResult stop() override;
|
||||
virtual KResult start() override;
|
||||
void spawn_port_proc();
|
||||
|
||||
void do_debug_transfer();
|
||||
|
||||
KResultOr<size_t> submit_control_transfer(Transfer& transfer);
|
||||
virtual KResultOr<size_t> submit_control_transfer(Transfer& transfer) override;
|
||||
|
||||
RefPtr<USB::Device> const get_device_at_port(USB::Device::PortNumber);
|
||||
RefPtr<USB::Device> const get_device_from_address(u8 device_address);
|
||||
virtual RefPtr<USB::Device> const get_device_at_port(USB::Device::PortNumber) override;
|
||||
virtual RefPtr<USB::Device> const get_device_from_address(u8 device_address) override;
|
||||
|
||||
private:
|
||||
UHCIController(PCI::Address, PCI::ID);
|
||||
explicit UHCIController(PCI::Address);
|
||||
|
||||
u16 read_usbcmd() { return m_io_base.offset(0).in<u16>(); }
|
||||
u16 read_usbsts() { return m_io_base.offset(0x2).in<u16>(); }
|
||||
|
|
17
Kernel/Bus/USB/USBController.cpp
Normal file
17
Kernel/Bus/USB/USBController.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Bus/USB/USBController.h>
|
||||
|
||||
namespace Kernel::USB {
|
||||
|
||||
u8 USBController::allocate_address()
|
||||
{
|
||||
// FIXME: This can be smarter.
|
||||
return m_next_device_index++;
|
||||
}
|
||||
|
||||
}
|
42
Kernel/Bus/USB/USBController.h
Normal file
42
Kernel/Bus/USB/USBController.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/RefCounted.h>
|
||||
#include <Kernel/Bus/USB/USBDevice.h>
|
||||
#include <Kernel/Bus/USB/USBTransfer.h>
|
||||
#include <Kernel/KResult.h>
|
||||
|
||||
namespace Kernel::USB {
|
||||
|
||||
class USBController : public RefCounted<USBController> {
|
||||
public:
|
||||
virtual ~USBController() = default;
|
||||
|
||||
virtual KResult initialize() = 0;
|
||||
|
||||
virtual KResult reset() = 0;
|
||||
virtual KResult stop() = 0;
|
||||
virtual KResult start() = 0;
|
||||
|
||||
virtual KResultOr<size_t> submit_control_transfer(Transfer&) = 0;
|
||||
|
||||
virtual RefPtr<USB::Device> const get_device_at_port(USB::Device::PortNumber) = 0;
|
||||
virtual RefPtr<USB::Device> const get_device_from_address(u8) = 0;
|
||||
|
||||
u8 allocate_address();
|
||||
|
||||
private:
|
||||
u8 m_next_device_index { 1 };
|
||||
|
||||
IntrusiveListNode<USBController, NonnullRefPtr<USBController>> m_controller_list_node;
|
||||
|
||||
public:
|
||||
using List = IntrusiveList<USBController, NonnullRefPtr<USBController>, &USBController::m_controller_list_node>;
|
||||
};
|
||||
|
||||
}
|
|
@ -5,24 +5,24 @@
|
|||
*/
|
||||
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <Kernel/Bus/USB/UHCIController.h>
|
||||
#include <Kernel/Bus/USB/USBController.h>
|
||||
#include <Kernel/Bus/USB/USBDescriptors.h>
|
||||
#include <Kernel/Bus/USB/USBDevice.h>
|
||||
#include <Kernel/Bus/USB/USBRequest.h>
|
||||
|
||||
static u32 s_next_usb_address = 1; // Next address we hand out to a device once it's plugged into the machine
|
||||
#include <Kernel/StdLib.h>
|
||||
|
||||
namespace Kernel::USB {
|
||||
|
||||
KResultOr<NonnullRefPtr<Device>> Device::try_create(PortNumber port, DeviceSpeed speed)
|
||||
KResultOr<NonnullRefPtr<Device>> Device::try_create(USBController const& controller, PortNumber port, DeviceSpeed speed)
|
||||
{
|
||||
auto pipe_or_error = Pipe::try_create_pipe(Pipe::Type::Control, Pipe::Direction::Bidirectional, 0, 8, 0);
|
||||
auto pipe_or_error = Pipe::try_create_pipe(controller, Pipe::Type::Control, Pipe::Direction::Bidirectional, 0, 8, 0);
|
||||
if (pipe_or_error.is_error())
|
||||
return pipe_or_error.error();
|
||||
|
||||
auto device = AK::try_create<Device>(port, speed, pipe_or_error.release_value());
|
||||
auto device = AK::try_create<Device>(controller, port, speed, pipe_or_error.release_value());
|
||||
if (!device)
|
||||
return ENOMEM;
|
||||
|
||||
|
@ -33,10 +33,11 @@ KResultOr<NonnullRefPtr<Device>> Device::try_create(PortNumber port, DeviceSpeed
|
|||
return device.release_nonnull();
|
||||
}
|
||||
|
||||
Device::Device(PortNumber port, DeviceSpeed speed, NonnullOwnPtr<Pipe> default_pipe)
|
||||
Device::Device(USBController const& controller, PortNumber port, DeviceSpeed speed, NonnullOwnPtr<Pipe> default_pipe)
|
||||
: m_device_port(port)
|
||||
, m_device_speed(speed)
|
||||
, m_address(0)
|
||||
, m_controller(controller)
|
||||
, m_default_pipe(move(default_pipe))
|
||||
{
|
||||
}
|
||||
|
@ -83,8 +84,10 @@ KResult Device::enumerate()
|
|||
dbgln("Number of configurations: {:02x}", dev_descriptor.num_configurations);
|
||||
}
|
||||
|
||||
m_address = m_controller->allocate_address();
|
||||
|
||||
// Attempt to set devices address on the bus
|
||||
transfer_length_or_error = m_default_pipe->control_transfer(USB_DEVICE_REQUEST_HOST_TO_DEVICE, USB_REQUEST_SET_ADDRESS, s_next_usb_address, 0, 0, nullptr);
|
||||
transfer_length_or_error = m_default_pipe->control_transfer(USB_DEVICE_REQUEST_HOST_TO_DEVICE, USB_REQUEST_SET_ADDRESS, m_address, 0, 0, nullptr);
|
||||
|
||||
if (transfer_length_or_error.is_error())
|
||||
return transfer_length_or_error.error();
|
||||
|
@ -92,7 +95,6 @@ KResult Device::enumerate()
|
|||
transfer_length = transfer_length_or_error.release_value();
|
||||
|
||||
VERIFY(transfer_length > 0);
|
||||
m_address = s_next_usb_address++;
|
||||
|
||||
memcpy(&m_device_descriptor, &dev_descriptor, sizeof(USBDeviceDescriptor));
|
||||
return KSuccess;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
namespace Kernel::USB {
|
||||
|
||||
class USBController;
|
||||
|
||||
//
|
||||
// Some nice info from FTDI on device enumeration and how some of this
|
||||
// glues together:
|
||||
|
@ -30,9 +32,9 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
static KResultOr<NonnullRefPtr<Device>> try_create(PortNumber, DeviceSpeed);
|
||||
static KResultOr<NonnullRefPtr<Device>> try_create(USBController const&, PortNumber, DeviceSpeed);
|
||||
|
||||
Device(PortNumber, DeviceSpeed, NonnullOwnPtr<Pipe> default_pipe);
|
||||
Device(USBController const&, PortNumber, DeviceSpeed, NonnullOwnPtr<Pipe> default_pipe);
|
||||
~Device();
|
||||
|
||||
KResult enumerate();
|
||||
|
@ -54,6 +56,7 @@ private:
|
|||
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
|
||||
|
||||
NonnullRefPtr<USBController> m_controller;
|
||||
NonnullOwnPtr<Pipe> m_default_pipe; // Default communication pipe (endpoint0) used during enumeration
|
||||
};
|
||||
}
|
||||
|
|
74
Kernel/Bus/USB/USBManagement.cpp
Normal file
74
Kernel/Bus/USB/USBManagement.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Singleton.h>
|
||||
#include <Kernel/Bus/PCI/Access.h>
|
||||
#include <Kernel/Bus/USB/UHCIController.h>
|
||||
#include <Kernel/Bus/USB/USBManagement.h>
|
||||
#include <Kernel/CommandLine.h>
|
||||
#include <Kernel/Sections.h>
|
||||
|
||||
namespace Kernel::USB {
|
||||
|
||||
static Singleton<USBManagement> s_the;
|
||||
|
||||
UNMAP_AFTER_INIT USBManagement::USBManagement()
|
||||
{
|
||||
enumerate_controllers();
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void USBManagement::enumerate_controllers()
|
||||
{
|
||||
if (!kernel_command_line().disable_usb()) {
|
||||
PCI::enumerate([this](PCI::Address const& address, PCI::ID) {
|
||||
if (PCI::get_class(address) == 0xc && PCI::get_subclass(address) == 0x3) {
|
||||
if (PCI::get_programming_interface(address) == 0x0) {
|
||||
if (kernel_command_line().disable_uhci_controller())
|
||||
return;
|
||||
|
||||
if (auto uhci_controller_or_error = UHCIController::try_to_initialize(address); !uhci_controller_or_error.is_error())
|
||||
m_controllers.append(uhci_controller_or_error.release_value());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (PCI::get_programming_interface(address) == 0x10) {
|
||||
dmesgln("USBManagement: OHCI controller found at {} is not currently supported.", address);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PCI::get_programming_interface(address) == 0x20) {
|
||||
dmesgln("USBManagement: EHCI controller found at {} is not currently supported.", address);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PCI::get_programming_interface(address) == 0x30) {
|
||||
dmesgln("USBManagement: xHCI controller found at {} is not currently supported.", address);
|
||||
return;
|
||||
}
|
||||
|
||||
dmesgln("USBManagement: Unknown/unsupported controller at {} with programming interface 0x{:02x}", address, PCI::get_programming_interface(address));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool USBManagement::initialized()
|
||||
{
|
||||
return s_the.is_initialized();
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void USBManagement::initialize()
|
||||
{
|
||||
s_the.ensure_instance();
|
||||
}
|
||||
|
||||
USBManagement& USBManagement::the()
|
||||
{
|
||||
return *s_the;
|
||||
}
|
||||
|
||||
}
|
30
Kernel/Bus/USB/USBManagement.h
Normal file
30
Kernel/Bus/USB/USBManagement.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/NonnullRefPtrVector.h>
|
||||
#include <Kernel/Bus/USB/USBController.h>
|
||||
|
||||
namespace Kernel::USB {
|
||||
|
||||
class USBManagement {
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
public:
|
||||
USBManagement();
|
||||
static bool initialized();
|
||||
static void initialize();
|
||||
static USBManagement& the();
|
||||
|
||||
private:
|
||||
void enumerate_controllers();
|
||||
|
||||
USBController::List m_controllers;
|
||||
};
|
||||
|
||||
}
|
|
@ -11,17 +11,18 @@
|
|||
|
||||
namespace Kernel::USB {
|
||||
|
||||
KResultOr<NonnullOwnPtr<Pipe>> Pipe::try_create_pipe(Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, u8 poll_interval)
|
||||
KResultOr<NonnullOwnPtr<Pipe>> Pipe::try_create_pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, u8 poll_interval)
|
||||
{
|
||||
auto pipe = adopt_own_if_nonnull(new (nothrow) Pipe(type, direction, endpoint_address, max_packet_size, device_address, poll_interval));
|
||||
auto pipe = adopt_own_if_nonnull(new (nothrow) Pipe(controller, type, direction, endpoint_address, max_packet_size, device_address, poll_interval));
|
||||
if (!pipe)
|
||||
return ENOMEM;
|
||||
|
||||
return pipe.release_nonnull();
|
||||
}
|
||||
|
||||
Pipe::Pipe(Type type, Pipe::Direction direction, u16 max_packet_size)
|
||||
: m_type(type)
|
||||
Pipe::Pipe(USBController const& controller, Type type, Pipe::Direction direction, u16 max_packet_size)
|
||||
: m_controller(controller)
|
||||
, m_type(type)
|
||||
, m_direction(direction)
|
||||
, m_endpoint_address(0)
|
||||
, m_max_packet_size(max_packet_size)
|
||||
|
@ -30,15 +31,17 @@ Pipe::Pipe(Type type, Pipe::Direction direction, u16 max_packet_size)
|
|||
{
|
||||
}
|
||||
|
||||
Pipe::Pipe(Type type, Direction direction, USBEndpointDescriptor& endpoint [[maybe_unused]])
|
||||
: m_type(type)
|
||||
Pipe::Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint [[maybe_unused]])
|
||||
: m_controller(controller)
|
||||
, m_type(type)
|
||||
, m_direction(direction)
|
||||
{
|
||||
// TODO: decode endpoint structure
|
||||
}
|
||||
|
||||
Pipe::Pipe(Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address)
|
||||
: m_type(type)
|
||||
Pipe::Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address)
|
||||
: m_controller(controller)
|
||||
, m_type(type)
|
||||
, m_direction(direction)
|
||||
, m_device_address(device_address)
|
||||
, m_endpoint_address(endpoint_address)
|
||||
|
@ -66,7 +69,7 @@ KResultOr<size_t> Pipe::control_transfer(u8 request_type, u8 request, u16 value,
|
|||
transfer->set_setup_packet(usb_request);
|
||||
|
||||
dbgln_if(USB_DEBUG, "Pipe: Transfer allocated @ {}", transfer->buffer_physical());
|
||||
auto transfer_len_or_error = UHCIController::the().submit_control_transfer(*transfer);
|
||||
auto transfer_len_or_error = m_controller->submit_control_transfer(*transfer);
|
||||
|
||||
if (transfer_len_or_error.is_error())
|
||||
return transfer_len_or_error.error();
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
namespace Kernel::USB {
|
||||
|
||||
class USBController;
|
||||
|
||||
//
|
||||
// A pipe is the logical connection between a memory buffer on the PC (host) and
|
||||
// an endpoint on the device. In this implementation, the data buffer the pipe connects
|
||||
|
@ -39,7 +41,7 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
static KResultOr<NonnullOwnPtr<Pipe>> try_create_pipe(Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, u8 poll_interval = 0);
|
||||
static KResultOr<NonnullOwnPtr<Pipe>> try_create_pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, u8 poll_interval = 0);
|
||||
|
||||
Type type() const { return m_type; }
|
||||
Direction direction() const { return m_direction; }
|
||||
|
@ -57,13 +59,15 @@ public:
|
|||
|
||||
KResultOr<size_t> control_transfer(u8 request_type, u8 request, u16 value, u16 index, u16 length, void* data);
|
||||
|
||||
Pipe(Type type, Direction direction, u16 max_packet_size);
|
||||
Pipe(Type type, Direction direction, USBEndpointDescriptor& endpoint);
|
||||
Pipe(Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address);
|
||||
Pipe(USBController const& controller, Type type, Direction direction, u16 max_packet_size);
|
||||
Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint);
|
||||
Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address);
|
||||
|
||||
private:
|
||||
friend class Device;
|
||||
|
||||
NonnullRefPtr<USBController> m_controller;
|
||||
|
||||
Type m_type;
|
||||
Direction m_direction;
|
||||
DeviceSpeed m_speed;
|
||||
|
|
|
@ -32,7 +32,9 @@ set(KERNEL_SOURCES
|
|||
Bus/PCI/Initializer.cpp
|
||||
Bus/PCI/WindowedMMIOAccess.cpp
|
||||
Bus/USB/UHCIController.cpp
|
||||
Bus/USB/USBController.cpp
|
||||
Bus/USB/USBDevice.cpp
|
||||
Bus/USB/USBManagement.cpp
|
||||
Bus/USB/USBPipe.cpp
|
||||
Bus/USB/USBTransfer.cpp
|
||||
CMOS.cpp
|
||||
|
|
|
@ -177,6 +177,11 @@ UNMAP_AFTER_INIT bool CommandLine::disable_uhci_controller() const
|
|||
return contains("disable_uhci_controller"sv);
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT bool CommandLine::disable_usb() const
|
||||
{
|
||||
return contains("disable_usb"sv);
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT bool CommandLine::disable_virtio() const
|
||||
{
|
||||
return contains("disable_virtio"sv);
|
||||
|
|
|
@ -73,6 +73,7 @@ public:
|
|||
[[nodiscard]] bool disable_physical_storage() const;
|
||||
[[nodiscard]] bool disable_ps2_controller() const;
|
||||
[[nodiscard]] bool disable_uhci_controller() const;
|
||||
[[nodiscard]] bool disable_usb() const;
|
||||
[[nodiscard]] bool disable_virtio() const;
|
||||
[[nodiscard]] AHCIResetMode ahci_reset_mode() const;
|
||||
[[nodiscard]] String userspace_init() const;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include <Kernel/BootInfo.h>
|
||||
#include <Kernel/Bus/PCI/Access.h>
|
||||
#include <Kernel/Bus/PCI/Initializer.h>
|
||||
#include <Kernel/Bus/USB/UHCIController.h>
|
||||
#include <Kernel/Bus/USB/USBManagement.h>
|
||||
#include <Kernel/CMOS.h>
|
||||
#include <Kernel/CommandLine.h>
|
||||
#include <Kernel/Devices/FullDevice.h>
|
||||
|
@ -300,7 +300,7 @@ void init_stage2(void*)
|
|||
|
||||
auto boot_profiling = kernel_command_line().is_boot_profiling_enabled();
|
||||
|
||||
USB::UHCIController::detect();
|
||||
USB::USBManagement::initialize();
|
||||
|
||||
BIOSSysFSDirectory::initialize();
|
||||
ACPI::ACPISysFSDirectory::initialize();
|
||||
|
|
Loading…
Reference in a new issue