summaryrefslogtreecommitdiff
path: root/Kernel/Bus
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Bus')
-rw-r--r--Kernel/Bus/USB/USBDevice.cpp8
-rw-r--r--Kernel/Bus/USB/USBDevice.h8
-rw-r--r--Kernel/Bus/USB/USBHub.cpp8
-rw-r--r--Kernel/Bus/USB/USBHub.h4
-rw-r--r--Kernel/Bus/USB/USBPipe.cpp128
-rw-r--r--Kernel/Bus/USB/USBPipe.h84
6 files changed, 175 insertions, 65 deletions
diff --git a/Kernel/Bus/USB/USBDevice.cpp b/Kernel/Bus/USB/USBDevice.cpp
index 955da88ae7..53a7f2a78e 100644
--- a/Kernel/Bus/USB/USBDevice.cpp
+++ b/Kernel/Bus/USB/USBDevice.cpp
@@ -18,7 +18,7 @@ namespace Kernel::USB {
ErrorOr<NonnullLockRefPtr<Device>> Device::try_create(USBController const& controller, u8 port, DeviceSpeed speed)
{
- auto pipe = TRY(Pipe::try_create_pipe(controller, Pipe::Type::Control, Pipe::Direction::Bidirectional, 0, 8, 0));
+ auto pipe = TRY(ControlPipe::create(controller, 0, 8, 0));
auto device = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) Device(controller, port, speed, move(pipe))));
auto sysfs_node = TRY(SysFSUSBDeviceInformation::create(*device));
device->m_sysfs_device_info_node = move(sysfs_node);
@@ -26,7 +26,7 @@ ErrorOr<NonnullLockRefPtr<Device>> Device::try_create(USBController const& contr
return device;
}
-Device::Device(USBController const& controller, u8 port, DeviceSpeed speed, NonnullOwnPtr<Pipe> default_pipe)
+Device::Device(USBController const& controller, u8 port, DeviceSpeed speed, NonnullOwnPtr<ControlPipe> default_pipe)
: m_device_port(port)
, m_device_speed(speed)
, m_address(0)
@@ -35,7 +35,7 @@ Device::Device(USBController const& controller, u8 port, DeviceSpeed speed, Nonn
{
}
-Device::Device(NonnullLockRefPtr<USBController> controller, u8 address, u8 port, DeviceSpeed speed, NonnullOwnPtr<Pipe> default_pipe)
+Device::Device(NonnullLockRefPtr<USBController> controller, u8 address, u8 port, DeviceSpeed speed, NonnullOwnPtr<ControlPipe> default_pipe)
: m_device_port(port)
, m_device_speed(speed)
, m_address(address)
@@ -44,7 +44,7 @@ Device::Device(NonnullLockRefPtr<USBController> controller, u8 address, u8 port,
{
}
-Device::Device(Device const& device, NonnullOwnPtr<Pipe> default_pipe)
+Device::Device(Device const& device, NonnullOwnPtr<ControlPipe> default_pipe)
: m_device_port(device.port())
, m_device_speed(device.speed())
, m_address(device.address())
diff --git a/Kernel/Bus/USB/USBDevice.h b/Kernel/Bus/USB/USBDevice.h
index 0eb5b20718..c1069b9939 100644
--- a/Kernel/Bus/USB/USBDevice.h
+++ b/Kernel/Bus/USB/USBDevice.h
@@ -36,8 +36,8 @@ public:
static ErrorOr<NonnullLockRefPtr<Device>> try_create(USBController const&, u8, DeviceSpeed);
- Device(USBController const&, u8, DeviceSpeed, NonnullOwnPtr<Pipe> default_pipe);
- Device(Device const& device, NonnullOwnPtr<Pipe> default_pipe);
+ Device(USBController const&, u8, DeviceSpeed, NonnullOwnPtr<ControlPipe> default_pipe);
+ Device(Device const& device, NonnullOwnPtr<ControlPipe> default_pipe);
virtual ~Device();
ErrorOr<void> enumerate_device();
@@ -59,7 +59,7 @@ public:
SysFSUSBDeviceInformation& sysfs_device_info_node(Badge<USB::Hub>) { return *m_sysfs_device_info_node; }
protected:
- Device(NonnullLockRefPtr<USBController> controller, u8 address, u8 port, DeviceSpeed speed, NonnullOwnPtr<Pipe> default_pipe);
+ Device(NonnullLockRefPtr<USBController> controller, u8 address, u8 port, DeviceSpeed speed, NonnullOwnPtr<ControlPipe> default_pipe);
u8 m_device_port { 0 }; // What port is this device attached to. NOTE: This is 1-based.
DeviceSpeed m_device_speed; // What speed is this device running at
@@ -72,7 +72,7 @@ protected:
Vector<USBConfiguration> m_configurations; // Configurations for this device
NonnullLockRefPtr<USBController> m_controller;
- NonnullOwnPtr<Pipe> m_default_pipe; // Default communication pipe (endpoint0) used during enumeration
+ NonnullOwnPtr<ControlPipe> m_default_pipe; // Default communication pipe (endpoint0) used during enumeration
private:
IntrusiveListNode<Device, NonnullLockRefPtr<Device>> m_hub_child_node;
diff --git a/Kernel/Bus/USB/USBHub.cpp b/Kernel/Bus/USB/USBHub.cpp
index bb80647ed2..629c00f299 100644
--- a/Kernel/Bus/USB/USBHub.cpp
+++ b/Kernel/Bus/USB/USBHub.cpp
@@ -18,25 +18,25 @@ namespace Kernel::USB {
ErrorOr<NonnullLockRefPtr<Hub>> Hub::try_create_root_hub(NonnullLockRefPtr<USBController> controller, DeviceSpeed device_speed)
{
// NOTE: Enumeration does not happen here, as the controller must know what the device address is at all times during enumeration to intercept requests.
- auto pipe = TRY(Pipe::try_create_pipe(controller, Pipe::Type::Control, Pipe::Direction::Bidirectional, 0, 8, 0));
+ auto pipe = TRY(ControlPipe::create(controller, 0, 8, 0));
auto hub = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) Hub(controller, device_speed, move(pipe))));
return hub;
}
ErrorOr<NonnullLockRefPtr<Hub>> Hub::try_create_from_device(Device const& device)
{
- auto pipe = TRY(Pipe::try_create_pipe(device.controller(), Pipe::Type::Control, Pipe::Direction::Bidirectional, 0, device.device_descriptor().max_packet_size, device.address()));
+ auto pipe = TRY(ControlPipe::create(device.controller(), 0, device.device_descriptor().max_packet_size, device.address()));
auto hub = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) Hub(device, move(pipe))));
TRY(hub->enumerate_and_power_on_hub());
return hub;
}
-Hub::Hub(NonnullLockRefPtr<USBController> controller, DeviceSpeed device_speed, NonnullOwnPtr<Pipe> default_pipe)
+Hub::Hub(NonnullLockRefPtr<USBController> controller, DeviceSpeed device_speed, NonnullOwnPtr<ControlPipe> default_pipe)
: Device(move(controller), 1 /* Port 1 */, device_speed, move(default_pipe))
{
}
-Hub::Hub(Device const& device, NonnullOwnPtr<Pipe> default_pipe)
+Hub::Hub(Device const& device, NonnullOwnPtr<ControlPipe> default_pipe)
: Device(device, move(default_pipe))
{
}
diff --git a/Kernel/Bus/USB/USBHub.h b/Kernel/Bus/USB/USBHub.h
index aaefe513d4..6108bf8828 100644
--- a/Kernel/Bus/USB/USBHub.h
+++ b/Kernel/Bus/USB/USBHub.h
@@ -96,9 +96,9 @@ public:
private:
// Root Hub constructor
- Hub(NonnullLockRefPtr<USBController>, DeviceSpeed, NonnullOwnPtr<Pipe> default_pipe);
+ Hub(NonnullLockRefPtr<USBController>, DeviceSpeed, NonnullOwnPtr<ControlPipe> default_pipe);
- Hub(Device const&, NonnullOwnPtr<Pipe> default_pipe);
+ Hub(Device const&, NonnullOwnPtr<ControlPipe> default_pipe);
USBHubDescriptor m_hub_descriptor {};
diff --git a/Kernel/Bus/USB/USBPipe.cpp b/Kernel/Bus/USB/USBPipe.cpp
index ab1cd8bb3b..ac4c79bc57 100644
--- a/Kernel/Bus/USB/USBPipe.cpp
+++ b/Kernel/Bus/USB/USBPipe.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
+ * Copyright (c) 2022, blackcat <b14ckcat@protonmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -12,48 +13,33 @@
namespace Kernel::USB {
-ErrorOr<NonnullOwnPtr<Pipe>> Pipe::try_create_pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size, u8 poll_interval)
-{
- auto dma_region = TRY(MM.allocate_dma_buffer_pages(TRY(Memory::page_round_up(buffer_size)), "USB device DMA buffer"sv, Memory::Region::Access::ReadWrite));
- return adopt_nonnull_own_or_enomem(new (nothrow) Pipe(controller, type, direction, endpoint_address, max_packet_size, poll_interval, device_address, move(dma_region)));
-}
-
-Pipe::Pipe(USBController const& controller, Type type, Pipe::Direction direction, u16 max_packet_size, NonnullOwnPtr<Memory::Region> dma_buffer)
+Pipe::Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer)
: m_controller(controller)
, m_type(type)
, m_direction(direction)
- , m_endpoint_address(0)
+ , m_device_address(device_address)
+ , m_endpoint_address(endpoint_address)
, m_max_packet_size(max_packet_size)
- , m_poll_interval(0)
, m_data_toggle(false)
, m_dma_buffer(move(dma_buffer))
{
}
-Pipe::Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint [[maybe_unused]], NonnullOwnPtr<Memory::Region> dma_buffer)
- : m_controller(controller)
- , m_type(type)
- , m_direction(direction)
- , m_dma_buffer(move(dma_buffer))
+ErrorOr<NonnullOwnPtr<ControlPipe>> ControlPipe::create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size)
{
- // TODO: decode endpoint structure
+ auto dma_buffer = TRY(MM.allocate_dma_buffer_pages(TRY(Memory::page_round_up(buffer_size)), "USB device DMA buffer"sv, Memory::Region::Access::ReadWrite));
+ return adopt_nonnull_own_or_enomem(new (nothrow) ControlPipe(controller, endpoint_address, max_packet_size, device_address, move(dma_buffer)));
}
-Pipe::Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer)
- : m_controller(controller)
- , m_type(type)
- , m_direction(direction)
- , m_device_address(device_address)
- , m_endpoint_address(endpoint_address)
- , m_max_packet_size(max_packet_size)
- , m_poll_interval(poll_interval)
- , m_data_toggle(false)
- , m_dma_buffer(move(dma_buffer))
+ControlPipe::ControlPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer)
+ : Pipe(controller, Type::Control, Direction::Bidirectional, endpoint_address, max_packet_size, device_address, move(dma_buffer))
{
}
-ErrorOr<size_t> Pipe::control_transfer(u8 request_type, u8 request, u16 value, u16 index, u16 length, void* data)
+ErrorOr<size_t> ControlPipe::control_transfer(u8 request_type, u8 request, u16 value, u16 index, size_t length, void* data)
{
+ VERIFY(length <= m_dma_buffer->size());
+
MutexLocker lock(m_dma_buffer_lock);
USBRequestData usb_request;
@@ -67,7 +53,7 @@ ErrorOr<size_t> Pipe::control_transfer(u8 request_type, u8 request, u16 value, u
auto transfer = TRY(Transfer::try_create(*this, length, *m_dma_buffer));
transfer->set_setup_packet(usb_request);
- dbgln_if(USB_DEBUG, "Pipe: Transfer allocated @ {}", transfer->buffer_physical());
+ dbgln_if(USB_DEBUG, "ControlPipe: Transfer allocated @ {}", transfer->buffer_physical());
auto transfer_length = TRY(m_controller->submit_control_transfer(*transfer));
// TODO: Check transfer for completion and copy data from transfer buffer into data
@@ -78,26 +64,90 @@ ErrorOr<size_t> Pipe::control_transfer(u8 request_type, u8 request, u16 value, u
return transfer_length;
}
-ErrorOr<size_t> Pipe::bulk_transfer(u16 length, void* data)
+ErrorOr<NonnullOwnPtr<BulkInPipe>> BulkInPipe::create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size)
{
+ VERIFY(buffer_size >= max_packet_size);
+ auto dma_buffer = TRY(MM.allocate_dma_buffer_pages(TRY(Memory::page_round_up(buffer_size)), "USB pipe DMA buffer"sv, Memory::Region::Access::ReadWrite));
+ return adopt_nonnull_own_or_enomem(new (nothrow) BulkInPipe(controller, endpoint_address, max_packet_size, device_address, move(dma_buffer)));
+}
+
+BulkInPipe::BulkInPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer)
+ : Pipe(controller, Pipe::Type::Bulk, Direction::In, endpoint_address, max_packet_size, device_address, move(dma_buffer))
+{
+}
+
+ErrorOr<size_t> BulkInPipe::bulk_in_transfer(size_t length, void* data)
+{
+ VERIFY(length <= m_dma_buffer->size());
+
MutexLocker lock(m_dma_buffer_lock);
size_t transfer_length = 0;
+
auto transfer = TRY(Transfer::try_create(*this, length, *m_dma_buffer));
- if (m_direction == Direction::In) {
- dbgln_if(USB_DEBUG, "Pipe: Bulk in transfer allocated @ {}", transfer->buffer_physical());
- transfer_length = TRY(m_controller->submit_bulk_transfer(*transfer));
- memcpy(data, transfer->buffer().as_ptr(), min(length, transfer_length));
- dbgln_if(USB_DEBUG, "Pipe: Bulk in transfer complete!");
- } else if (m_direction == Direction::Out) {
- TRY(transfer->write_buffer(length, data));
- dbgln_if(USB_DEBUG, "Pipe: Bulk out transfer allocated @ {}", transfer->buffer_physical());
- transfer_length = TRY(m_controller->submit_bulk_transfer(*transfer));
- dbgln_if(USB_DEBUG, "Pipe: Bulk out transfer complete!");
- }
+ dbgln_if(USB_DEBUG, "Pipe: Bulk in transfer allocated @ {}", transfer->buffer_physical());
+ transfer_length = TRY(m_controller->submit_bulk_transfer(*transfer));
+ memcpy(data, transfer->buffer().as_ptr(), min(length, transfer_length));
+ dbgln_if(USB_DEBUG, "Pipe: Bulk in transfer complete!");
return transfer_length;
}
+ErrorOr<NonnullOwnPtr<BulkOutPipe>> BulkOutPipe::create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size)
+{
+ VERIFY(buffer_size >= max_packet_size);
+ auto dma_buffer = TRY(MM.allocate_dma_buffer_pages(TRY(Memory::page_round_up(buffer_size)), "USB pipe DMA buffer"sv, Memory::Region::Access::ReadWrite));
+ return adopt_nonnull_own_or_enomem(new (nothrow) BulkOutPipe(controller, endpoint_address, max_packet_size, device_address, move(dma_buffer)));
+}
+
+BulkOutPipe::BulkOutPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer)
+ : Pipe(controller, Type::Bulk, Direction::Out, endpoint_address, max_packet_size, device_address, move(dma_buffer))
+
+{
+}
+
+ErrorOr<size_t> BulkOutPipe::bulk_out_transfer(size_t length, void* data)
+{
+ VERIFY(length <= m_dma_buffer->size());
+
+ MutexLocker lock(m_dma_buffer_lock);
+
+ size_t transfer_length = 0;
+ auto transfer = TRY(Transfer::try_create(*this, length, *m_dma_buffer));
+
+ TRY(transfer->write_buffer(length, data));
+ dbgln_if(USB_DEBUG, "Pipe: Bulk out transfer allocated @ {}", transfer->buffer_physical());
+ transfer_length = TRY(m_controller->submit_bulk_transfer(*transfer));
+ dbgln_if(USB_DEBUG, "Pipe: Bulk out transfer complete!");
+
+ return transfer_length;
+}
+
+ErrorOr<NonnullOwnPtr<InterruptInPipe>> InterruptInPipe::create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, u16 poll_interval, size_t buffer_size)
+{
+ VERIFY(buffer_size >= max_packet_size);
+ auto dma_buffer = TRY(MM.allocate_dma_buffer_pages(TRY(Memory::page_round_up(buffer_size)), "USB pipe DMA buffer"sv, Memory::Region::Access::ReadWrite));
+ return adopt_nonnull_own_or_enomem(new (nothrow) InterruptInPipe(controller, endpoint_address, max_packet_size, device_address, poll_interval, move(dma_buffer)));
+}
+
+InterruptInPipe::InterruptInPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, u16 poll_interval, NonnullOwnPtr<Memory::Region> dma_buffer)
+ : Pipe(controller, Type::Interrupt, Direction::In, endpoint_address, max_packet_size, device_address, move(dma_buffer))
+ , m_poll_interval(poll_interval)
+{
+}
+
+ErrorOr<NonnullOwnPtr<InterruptOutPipe>> InterruptOutPipe::create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, u16 poll_interval, size_t buffer_size)
+{
+ VERIFY(buffer_size >= max_packet_size);
+ auto dma_buffer = TRY(MM.allocate_dma_buffer_pages(TRY(Memory::page_round_up(buffer_size)), "USB pipe DMA buffer"sv, Memory::Region::Access::ReadWrite));
+ return adopt_nonnull_own_or_enomem(new (nothrow) InterruptOutPipe(controller, endpoint_address, max_packet_size, device_address, poll_interval, move(dma_buffer)));
+}
+
+InterruptOutPipe::InterruptOutPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, u16 poll_interval, NonnullOwnPtr<Memory::Region> dma_buffer)
+ : Pipe(controller, Type::Interrupt, Direction::In, endpoint_address, max_packet_size, device_address, move(dma_buffer))
+ , m_poll_interval(poll_interval)
+{
+}
+
}
diff --git a/Kernel/Bus/USB/USBPipe.h b/Kernel/Bus/USB/USBPipe.h
index 73c423b2d2..578852dc0f 100644
--- a/Kernel/Bus/USB/USBPipe.h
+++ b/Kernel/Bus/USB/USBPipe.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
+ * Copyright (c) 2022, blackcat <b14ckcat@protonmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -15,6 +16,7 @@
namespace Kernel::USB {
class USBController;
+class Transfer;
//
// A pipe is the logical connection between a memory buffer on the PC (host) and
@@ -41,8 +43,6 @@ public:
FullSpeed
};
- static ErrorOr<NonnullOwnPtr<Pipe>> try_create_pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size = PAGE_SIZE, u8 poll_interval = 0);
-
Type type() const { return m_type; }
Direction direction() const { return m_direction; }
DeviceSpeed device_speed() const { return m_speed; }
@@ -50,23 +50,17 @@ public:
i8 device_address() const { return m_device_address; }
u8 endpoint_address() const { return m_endpoint_address; }
u16 max_packet_size() const { return m_max_packet_size; }
- u8 poll_interval() const { return m_poll_interval; }
bool data_toggle() const { return m_data_toggle; }
void set_max_packet_size(u16 max_size) { m_max_packet_size = max_size; }
void set_toggle(bool toggle) { m_data_toggle = toggle; }
void set_device_address(i8 addr) { m_device_address = addr; }
- ErrorOr<size_t> control_transfer(u8 request_type, u8 request, u16 value, u16 index, u16 length, void* data);
- ErrorOr<size_t> bulk_transfer(u16 length, void* data);
-
- Pipe(USBController const& controller, Type type, Direction direction, u16 max_packet_size, NonnullOwnPtr<Memory::Region> dma_buffer);
- Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint, NonnullOwnPtr<Memory::Region> dma_buffer);
- Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer);
-
-private:
+protected:
friend class Device;
+ Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer);
+
NonnullLockRefPtr<USBController> m_controller;
Type m_type;
@@ -76,11 +70,77 @@ private:
i8 m_device_address { 0 }; // Device address of this pipe
u8 m_endpoint_address { 0 }; // Corresponding endpoint address for this pipe
u16 m_max_packet_size { 0 }; // Max packet size for this pipe
- u8 m_poll_interval { 0 }; // Polling interval (in frames)
bool m_data_toggle { false }; // Data toggle for stuffing bit
Mutex m_dma_buffer_lock { "USB pipe mutex"sv };
NonnullOwnPtr<Memory::Region> m_dma_buffer;
};
+
+class ControlPipe : public Pipe {
+public:
+ static ErrorOr<NonnullOwnPtr<ControlPipe>> create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size = PAGE_SIZE);
+
+ ErrorOr<size_t> control_transfer(u8 request_type, u8 request, u16 value, u16 index, size_t length, void* data);
+
+private:
+ ControlPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer);
+};
+
+class BulkInPipe : public Pipe {
+public:
+ static ErrorOr<NonnullOwnPtr<BulkInPipe>> create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size = PAGE_SIZE);
+
+ ErrorOr<size_t> bulk_in_transfer(size_t length, void* data);
+
+private:
+ BulkInPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer);
+};
+
+class BulkOutPipe : public Pipe {
+public:
+ static ErrorOr<NonnullOwnPtr<BulkOutPipe>> create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size = PAGE_SIZE);
+
+ ErrorOr<size_t> bulk_out_transfer(size_t length, void* data);
+
+private:
+ BulkOutPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer);
+};
+
+class InterruptInPipe : public Pipe {
+public:
+ static ErrorOr<NonnullOwnPtr<InterruptInPipe>> create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, u16 poll_interval, size_t buffer_size = PAGE_SIZE);
+
+ u16 poll_interval() const { return m_poll_interval; }
+
+private:
+ InterruptInPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, u16 poll_interval, NonnullOwnPtr<Memory::Region> dma_pool);
+
+ u16 m_poll_interval;
+};
+
+class InterruptOutPipe : public Pipe {
+public:
+ static ErrorOr<NonnullOwnPtr<InterruptOutPipe>> create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, u16 poll_interval, size_t buffer_size = PAGE_SIZE);
+
+ u16 poll_interval() const { return m_poll_interval; }
+
+private:
+ InterruptOutPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, u16 poll_interval, NonnullOwnPtr<Memory::Region> dma_pool);
+
+ u16 m_poll_interval;
+};
+
+class IsochronousInPipe : public Pipe {
+ // TODO
+public:
+private:
+};
+
+class IsochronousOutPipe : public Pipe {
+ // TODO
+public:
+private:
+};
+
}