diff --git a/Kernel/Bus/USB/USBPipe.cpp b/Kernel/Bus/USB/USBPipe.cpp index 088e7c5105a..417ae2f77c4 100644 --- a/Kernel/Bus/USB/USBPipe.cpp +++ b/Kernel/Bus/USB/USBPipe.cpp @@ -94,6 +94,22 @@ ErrorOr BulkInPipe::submit_bulk_in_transfer(size_t length, void* data) return transfer_length; } +ErrorOr BulkInPipe::submit_bulk_in_transfer(size_t length, UserOrKernelBuffer data) +{ + VERIFY(length <= m_dma_buffer->size()); + + MutexLocker lock(m_dma_buffer_lock); + + auto transfer = TRY(Transfer::create(*this, length, *m_dma_buffer)); + + dbgln_if(USB_DEBUG, "Pipe: Bulk in transfer allocated @ {}", transfer->buffer_physical()); + size_t transfer_length = TRY(m_controller->submit_bulk_transfer(*transfer)); + TRY(data.write(transfer->buffer().as_ptr(), min(length, transfer_length))); + dbgln_if(USB_DEBUG, "Pipe: Bulk in transfer complete!"); + + return transfer_length; +} + ErrorOr> 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); @@ -124,6 +140,22 @@ ErrorOr BulkOutPipe::submit_bulk_out_transfer(size_t length, void* data) return transfer_length; } +ErrorOr BulkOutPipe::submit_bulk_out_transfer(size_t length, UserOrKernelBuffer data) +{ + VERIFY(length <= m_dma_buffer->size()); + + MutexLocker lock(m_dma_buffer_lock); + + auto transfer = TRY(Transfer::create(*this, length, *m_dma_buffer)); + + TRY(transfer->write_buffer(length, data)); + dbgln_if(USB_DEBUG, "Pipe: Bulk out transfer allocated @ {}", transfer->buffer_physical()); + size_t transfer_length = TRY(m_controller->submit_bulk_transfer(*transfer)); + dbgln_if(USB_DEBUG, "Pipe: Bulk out transfer complete!"); + + return transfer_length; +} + ErrorOr> 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); diff --git a/Kernel/Bus/USB/USBPipe.h b/Kernel/Bus/USB/USBPipe.h index 644138be38b..f0bcb2e1555 100644 --- a/Kernel/Bus/USB/USBPipe.h +++ b/Kernel/Bus/USB/USBPipe.h @@ -94,6 +94,7 @@ public: static ErrorOr> create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size = PAGE_SIZE); ErrorOr submit_bulk_in_transfer(size_t length, void* data); + ErrorOr submit_bulk_in_transfer(size_t length, UserOrKernelBuffer data); private: BulkInPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr dma_buffer); @@ -104,6 +105,7 @@ public: static ErrorOr> create(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, size_t buffer_size = PAGE_SIZE); ErrorOr submit_bulk_out_transfer(size_t length, void* data); + ErrorOr submit_bulk_out_transfer(size_t length, UserOrKernelBuffer data); private: BulkOutPipe(USBController const& controller, u8 endpoint_address, u16 max_packet_size, i8 device_address, NonnullOwnPtr dma_buffer); diff --git a/Kernel/Bus/USB/USBTransfer.cpp b/Kernel/Bus/USB/USBTransfer.cpp index 88959720a3b..30dede2f0d3 100644 --- a/Kernel/Bus/USB/USBTransfer.cpp +++ b/Kernel/Bus/USB/USBTransfer.cpp @@ -6,6 +6,7 @@ #include #include +#include #include namespace Kernel::USB { @@ -51,6 +52,13 @@ ErrorOr Transfer::write_buffer(u16 len, void* data) return {}; } +ErrorOr Transfer::write_buffer(u16 len, UserOrKernelBuffer data) +{ + VERIFY(len <= m_dma_buffer.size()); + m_transfer_data_size = len; + return data.read(buffer().as_ptr(), len); +} + void Transfer::invoke_async_callback() { if (m_callback) diff --git a/Kernel/Bus/USB/USBTransfer.h b/Kernel/Bus/USB/USBTransfer.h index c506650d9ec..b5fa8a472ad 100644 --- a/Kernel/Bus/USB/USBTransfer.h +++ b/Kernel/Bus/USB/USBTransfer.h @@ -30,6 +30,7 @@ public: void set_error_occurred() { m_error_occurred = true; } ErrorOr write_buffer(u16 len, void* data); + ErrorOr write_buffer(u16 len, UserOrKernelBuffer data); // `const` here makes sure we don't blow up by writing to a physical address USBRequestData const& request() const { return m_request; }