Strongly-typed IN vs OUT buffer types
This commit is contained in:
parent
a6baa5957e
commit
81cb48daa5
10 changed files with 221 additions and 84 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use futures_lite::future::block_on;
|
||||
use nusb::TransferStatus;
|
||||
use nusb::transfer::{RequestBuffer, TransferStatus};
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
|
@ -13,11 +13,11 @@ fn main() {
|
|||
let device = di.open().unwrap();
|
||||
let interface = device.claim_interface(0).unwrap();
|
||||
|
||||
let mut queue = interface.bulk_queue(0x81);
|
||||
let mut queue = interface.bulk_in_queue(0x81);
|
||||
|
||||
loop {
|
||||
while queue.pending() < 8 {
|
||||
queue.submit(Vec::with_capacity(256));
|
||||
queue.submit(RequestBuffer::new(256));
|
||||
}
|
||||
let result = block_on(queue.next_complete());
|
||||
println!("{result:?}");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use futures_lite::future::block_on;
|
||||
use nusb::{ControlIn, ControlOut, ControlType, Recipient};
|
||||
use nusb::transfer::{ControlIn, ControlOut, ControlType, Recipient};
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
|
@ -13,7 +13,7 @@ fn main() {
|
|||
let device = di.open().unwrap();
|
||||
let interface = device.claim_interface(0).unwrap();
|
||||
|
||||
let result = block_on(interface.control_transfer_out(ControlOut {
|
||||
let result = block_on(interface.control_out(ControlOut {
|
||||
control_type: ControlType::Vendor,
|
||||
recipient: Recipient::Device,
|
||||
request: 0x81,
|
||||
|
|
@ -23,7 +23,7 @@ fn main() {
|
|||
}));
|
||||
println!("{result:?}");
|
||||
|
||||
let result = block_on(interface.control_transfer_in(ControlIn {
|
||||
let result = block_on(interface.control_in(ControlIn {
|
||||
control_type: ControlType::Vendor,
|
||||
recipient: Recipient::Device,
|
||||
request: 0x81,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
use std::{
|
||||
collections::VecDeque,
|
||||
future::{poll_fn, Future},
|
||||
marker::PhantomData,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
control::{ControlIn, ControlOut},
|
||||
platform,
|
||||
transfer_internal::TransferHandle,
|
||||
Completion, DeviceInfo, EndpointType, Error, TransferFuture,
|
||||
transfer::{
|
||||
Completion, ControlIn, ControlOut, EndpointType, PlatformSubmit, RequestBuffer,
|
||||
TransferFuture, TransferHandle, TransferRequest,
|
||||
},
|
||||
DeviceInfo, Error,
|
||||
};
|
||||
|
||||
type Buffer = Vec<u8>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Device {
|
||||
backend: Arc<crate::platform::Device>,
|
||||
|
|
@ -47,29 +48,39 @@ impl Interface {
|
|||
todo!()
|
||||
}
|
||||
|
||||
pub fn control_transfer_in(&self, data: ControlIn) -> TransferFuture<ControlIn> {
|
||||
pub fn control_in(&self, data: ControlIn) -> TransferFuture<ControlIn> {
|
||||
let mut t = self.backend.make_transfer(0, EndpointType::Control);
|
||||
t.submit::<ControlIn>(data);
|
||||
TransferFuture::new(t)
|
||||
}
|
||||
|
||||
pub fn control_transfer_out(&self, data: ControlOut) -> TransferFuture<ControlOut> {
|
||||
pub fn control_out(&self, data: ControlOut) -> TransferFuture<ControlOut> {
|
||||
let mut t = self.backend.make_transfer(0, EndpointType::Control);
|
||||
t.submit::<ControlOut>(data);
|
||||
TransferFuture::new(t)
|
||||
}
|
||||
|
||||
pub fn bulk_transfer(&self, endpoint: u8, buf: Vec<u8>) -> TransferFuture<Vec<u8>> {
|
||||
pub fn bulk_in(&self, endpoint: u8, buf: RequestBuffer) -> TransferFuture<RequestBuffer> {
|
||||
let mut t = self.backend.make_transfer(endpoint, EndpointType::Bulk);
|
||||
t.submit(buf);
|
||||
TransferFuture::new(t)
|
||||
}
|
||||
|
||||
pub fn bulk_queue(&self, endpoint: u8) -> Queue {
|
||||
pub fn bulk_out(&self, endpoint: u8, buf: Vec<u8>) -> TransferFuture<Vec<u8>> {
|
||||
let mut t = self.backend.make_transfer(endpoint, EndpointType::Bulk);
|
||||
t.submit(buf);
|
||||
TransferFuture::new(t)
|
||||
}
|
||||
|
||||
pub fn bulk_in_queue(&self, endpoint: u8) -> Queue<RequestBuffer> {
|
||||
Queue::new(self.backend.clone(), endpoint, EndpointType::Bulk)
|
||||
}
|
||||
|
||||
pub fn interrupt_transfer(&self, endpoint: u8, buf: Vec<u8>) -> TransferFuture<Vec<u8>> {
|
||||
pub fn bulk_out_queue(&self, endpoint: u8) -> Queue<Vec<u8>> {
|
||||
Queue::new(self.backend.clone(), endpoint, EndpointType::Bulk)
|
||||
}
|
||||
|
||||
pub fn interrupt_in(&self, endpoint: u8, buf: RequestBuffer) -> TransferFuture<RequestBuffer> {
|
||||
let mut t = self
|
||||
.backend
|
||||
.make_transfer(endpoint, EndpointType::Interrupt);
|
||||
|
|
@ -77,12 +88,24 @@ impl Interface {
|
|||
TransferFuture::new(t)
|
||||
}
|
||||
|
||||
pub fn interrupt_queue(&self, endpoint: u8) -> Queue {
|
||||
pub fn interrupt_out(&self, endpoint: u8, buf: Vec<u8>) -> TransferFuture<Vec<u8>> {
|
||||
let mut t = self
|
||||
.backend
|
||||
.make_transfer(endpoint, EndpointType::Interrupt);
|
||||
t.submit(buf);
|
||||
TransferFuture::new(t)
|
||||
}
|
||||
|
||||
pub fn interrupt_in_queue(&self, endpoint: u8) -> Queue<RequestBuffer> {
|
||||
Queue::new(self.backend.clone(), endpoint, EndpointType::Interrupt)
|
||||
}
|
||||
|
||||
pub fn interrupt_out_queue(&self, endpoint: u8) -> Queue<Vec<u8>> {
|
||||
Queue::new(self.backend.clone(), endpoint, EndpointType::Interrupt)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Queue {
|
||||
pub struct Queue<R: TransferRequest> {
|
||||
interface: Arc<platform::Interface>,
|
||||
endpoint: u8,
|
||||
endpoint_type: EndpointType,
|
||||
|
|
@ -92,33 +115,32 @@ pub struct Queue {
|
|||
|
||||
/// An idle transfer that recently completed for re-use. Limiting
|
||||
cached: Option<TransferHandle<platform::TransferData>>,
|
||||
|
||||
bufs: PhantomData<R>,
|
||||
}
|
||||
|
||||
impl Queue {
|
||||
impl<R> Queue<R>
|
||||
where
|
||||
R: TransferRequest,
|
||||
platform::TransferData: PlatformSubmit<R>,
|
||||
{
|
||||
fn new(
|
||||
interface: Arc<platform::Interface>,
|
||||
endpoint: u8,
|
||||
endpoint_type: EndpointType,
|
||||
) -> Queue {
|
||||
) -> Queue<R> {
|
||||
Queue {
|
||||
interface,
|
||||
endpoint,
|
||||
endpoint_type,
|
||||
pending: VecDeque::new(),
|
||||
cached: None,
|
||||
bufs: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Submit a new transfer on the endpoint.
|
||||
///
|
||||
/// For an IN endpoint, the transfer size is set by the *capacity* of
|
||||
/// the buffer, and the length and current contents are ignored. The
|
||||
/// buffer is returned from a later call to `complete` filled with
|
||||
/// the data read from the endpoint.
|
||||
///
|
||||
/// For an OUT endpoint, the contents of the buffer are written to
|
||||
/// the endpoint.
|
||||
pub fn submit(&mut self, data: Buffer) {
|
||||
pub fn submit(&mut self, data: R) {
|
||||
let mut transfer = self.cached.take().unwrap_or_else(|| {
|
||||
self.interface
|
||||
.make_transfer(self.endpoint, self.endpoint_type)
|
||||
|
|
@ -130,20 +152,14 @@ impl Queue {
|
|||
/// Block waiting for the next pending transfer to complete, and return
|
||||
/// its buffer or an error status.
|
||||
///
|
||||
/// For an IN endpoint, the returned buffer contains the data
|
||||
/// read from the device.
|
||||
///
|
||||
/// For an OUT endpoint, the buffer is unmodified, but can be
|
||||
/// reused for another transfer.
|
||||
///
|
||||
/// Panics if there are no transfers pending.
|
||||
pub fn next_complete<'a>(&'a mut self) -> impl Future<Output = Completion<Vec<u8>>> + 'a {
|
||||
pub fn next_complete<'a>(&'a mut self) -> impl Future<Output = Completion<R::Response>> + 'a {
|
||||
poll_fn(|cx| {
|
||||
let res = self
|
||||
.pending
|
||||
.front_mut()
|
||||
.expect("queue should have pending transfers when calling next_complete")
|
||||
.poll_completion::<Vec<u8>>(cx);
|
||||
.poll_completion::<R>(cx);
|
||||
if res.is_ready() {
|
||||
self.cached = self.pending.pop_front();
|
||||
}
|
||||
|
|
@ -168,7 +184,7 @@ impl Queue {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for Queue {
|
||||
impl<R: TransferRequest> Drop for Queue<R> {
|
||||
fn drop(&mut self) {
|
||||
// Cancel transfers in reverse order to ensure subsequent transfers can't complete
|
||||
// out of order while we're going through them.
|
||||
|
|
|
|||
|
|
@ -3,18 +3,12 @@ use std::io;
|
|||
pub mod platform;
|
||||
pub use platform::list_devices;
|
||||
|
||||
mod control;
|
||||
pub use control::{ControlIn, ControlOut, ControlType, Direction, Recipient};
|
||||
|
||||
mod enumeration;
|
||||
pub use enumeration::{DeviceInfo, Speed, UnknownValue};
|
||||
|
||||
mod device;
|
||||
use device::Device;
|
||||
|
||||
mod transfer;
|
||||
pub use transfer::{Completion, EndpointType, TransferFuture, TransferStatus};
|
||||
|
||||
mod transfer_internal;
|
||||
pub mod transfer;
|
||||
|
||||
pub type Error = io::Error;
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ use super::{
|
|||
usbfs::{self, Urb},
|
||||
};
|
||||
use crate::{
|
||||
transfer_internal::{self, TransferHandle},
|
||||
DeviceInfo, EndpointType, Error,
|
||||
transfer::{notify_completion, EndpointType, TransferHandle},
|
||||
DeviceInfo, Error,
|
||||
};
|
||||
|
||||
pub(crate) struct LinuxDevice {
|
||||
|
|
@ -66,7 +66,7 @@ impl LinuxDevice {
|
|||
};
|
||||
|
||||
// SAFETY: pointer came from submit via kernel an we're now done with it
|
||||
unsafe { transfer_internal::notify_completion::<super::TransferData>(user_data) }
|
||||
unsafe { notify_completion::<super::TransferData>(user_data) }
|
||||
}
|
||||
Err(Errno::AGAIN) => {}
|
||||
Err(Errno::NODEV) => {
|
||||
|
|
@ -143,7 +143,7 @@ impl LinuxInterface {
|
|||
u.actual_length = 0;
|
||||
u.status = e.raw_os_error();
|
||||
}
|
||||
transfer_internal::notify_completion::<super::TransferData>(urb as *mut c_void)
|
||||
notify_completion::<super::TransferData>(urb as *mut c_void)
|
||||
}
|
||||
} else {
|
||||
debug!("Submitted URB {urb:?} on ep {ep:x}");
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ use std::{
|
|||
|
||||
use rustix::io::Errno;
|
||||
|
||||
use crate::{
|
||||
control::{ControlIn, ControlOut, SETUP_PACKET_SIZE},
|
||||
transfer_internal, Completion, EndpointType, TransferStatus,
|
||||
use crate::transfer::{
|
||||
Completion, ControlIn, ControlOut, EndpointType, PlatformSubmit, PlatformTransfer,
|
||||
RequestBuffer, ResponseBuffer, TransferStatus, SETUP_PACKET_SIZE,
|
||||
};
|
||||
|
||||
use super::usbfs::{
|
||||
|
|
@ -23,7 +23,7 @@ use super::usbfs::{
|
|||
/// It also owns the `urb` allocation itself, which is stored out-of-line
|
||||
/// to avoid violating noalias when submitting the transfer while holding
|
||||
/// `&mut TransferData`.
|
||||
pub(crate) struct TransferData {
|
||||
pub struct TransferData {
|
||||
urb: *mut Urb,
|
||||
capacity: usize,
|
||||
interface: Arc<super::Interface>,
|
||||
|
|
@ -35,7 +35,7 @@ impl TransferData {
|
|||
pub(super) fn new(
|
||||
interface: Arc<super::Interface>,
|
||||
endpoint: u8,
|
||||
ep_type: crate::EndpointType,
|
||||
ep_type: EndpointType,
|
||||
) -> TransferData {
|
||||
let ep_type = match ep_type {
|
||||
EndpointType::Control => USBDEVFS_URB_TYPE_CONTROL,
|
||||
|
|
@ -101,7 +101,7 @@ impl Drop for TransferData {
|
|||
}
|
||||
}
|
||||
|
||||
impl transfer_internal::PlatformTransfer for TransferData {
|
||||
impl PlatformTransfer for TransferData {
|
||||
fn cancel(&self) {
|
||||
unsafe {
|
||||
self.interface.cancel_urb(self.urb);
|
||||
|
|
@ -109,7 +109,7 @@ impl transfer_internal::PlatformTransfer for TransferData {
|
|||
}
|
||||
}
|
||||
|
||||
impl transfer_internal::PlatformSubmit<Vec<u8>> for TransferData {
|
||||
impl PlatformSubmit<Vec<u8>> for TransferData {
|
||||
unsafe fn submit(&mut self, data: Vec<u8>, user_data: *mut c_void) {
|
||||
let ep = self.urb_mut().endpoint;
|
||||
let len = if ep & 0x80 == 0 {
|
||||
|
|
@ -123,6 +123,30 @@ impl transfer_internal::PlatformSubmit<Vec<u8>> for TransferData {
|
|||
unsafe { self.interface.submit_urb(self.urb) }
|
||||
}
|
||||
|
||||
unsafe fn take_completed(&mut self) -> Completion<ResponseBuffer> {
|
||||
let status = urb_status(self.urb_mut());
|
||||
let len = self.urb_mut().actual_length as usize;
|
||||
|
||||
// SAFETY: self is completed (precondition)
|
||||
let data = ResponseBuffer::from_vec(self.take_buf(0), len);
|
||||
Completion { data, status }
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformSubmit<RequestBuffer> for TransferData {
|
||||
unsafe fn submit(&mut self, data: RequestBuffer, user_data: *mut c_void) {
|
||||
let ep = self.urb_mut().endpoint;
|
||||
let ty = self.urb_mut().ep_type;
|
||||
assert!(ep & 0x80 == 0x80);
|
||||
assert!(ty == USBDEVFS_URB_TYPE_BULK || ty == USBDEVFS_URB_TYPE_INTERRUPT);
|
||||
|
||||
let (data, len) = data.into_vec();
|
||||
self.fill(data, len, user_data);
|
||||
|
||||
// SAFETY: we just properly filled the buffer and it is not already pending
|
||||
unsafe { self.interface.submit_urb(self.urb) }
|
||||
}
|
||||
|
||||
unsafe fn take_completed(&mut self) -> Completion<Vec<u8>> {
|
||||
let status = urb_status(self.urb_mut());
|
||||
let len = self.urb_mut().actual_length as usize;
|
||||
|
|
@ -133,7 +157,7 @@ impl transfer_internal::PlatformSubmit<Vec<u8>> for TransferData {
|
|||
}
|
||||
}
|
||||
|
||||
impl transfer_internal::PlatformSubmit<ControlIn> for TransferData {
|
||||
impl PlatformSubmit<ControlIn> for TransferData {
|
||||
unsafe fn submit(&mut self, data: ControlIn, user_data: *mut c_void) {
|
||||
let buf_len = SETUP_PACKET_SIZE + data.length as usize;
|
||||
let mut buf = Vec::with_capacity(buf_len);
|
||||
|
|
@ -156,7 +180,7 @@ impl transfer_internal::PlatformSubmit<ControlIn> for TransferData {
|
|||
}
|
||||
}
|
||||
|
||||
impl transfer_internal::PlatformSubmit<ControlOut<'_>> for TransferData {
|
||||
impl PlatformSubmit<ControlOut<'_>> for TransferData {
|
||||
unsafe fn submit(&mut self, data: ControlOut, user_data: *mut c_void) {
|
||||
let buf_len = SETUP_PACKET_SIZE + data.data.len();
|
||||
let mut buf = Vec::with_capacity(buf_len);
|
||||
|
|
@ -172,11 +196,11 @@ impl transfer_internal::PlatformSubmit<ControlOut<'_>> for TransferData {
|
|||
unsafe { self.interface.submit_urb(self.urb) }
|
||||
}
|
||||
|
||||
unsafe fn take_completed(&mut self) -> Completion<usize> {
|
||||
unsafe fn take_completed(&mut self) -> Completion<ResponseBuffer> {
|
||||
let status = urb_status(self.urb_mut());
|
||||
let len = self.urb_mut().actual_length as usize;
|
||||
drop(self.take_buf(0));
|
||||
Completion { data: len, status }
|
||||
let data = ResponseBuffer::from_vec(self.take_buf(0), len);
|
||||
Completion { data, status }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
98
src/transfer/buffer.rs
Normal file
98
src/transfer/buffer.rs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
use std::fmt::Debug;
|
||||
use std::mem::ManuallyDrop;
|
||||
|
||||
use super::TransferRequest;
|
||||
|
||||
pub struct RequestBuffer {
|
||||
pub(crate) buf: *mut u8,
|
||||
pub(crate) capacity: usize,
|
||||
pub(crate) requested: usize,
|
||||
}
|
||||
|
||||
impl RequestBuffer {
|
||||
pub fn new(len: usize) -> RequestBuffer {
|
||||
let mut v = ManuallyDrop::new(Vec::with_capacity(len));
|
||||
RequestBuffer {
|
||||
buf: v.as_mut_ptr(),
|
||||
capacity: v.capacity(),
|
||||
requested: len,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn into_vec(self) -> (Vec<u8>, usize) {
|
||||
let s = ManuallyDrop::new(self);
|
||||
let v = unsafe { Vec::from_raw_parts(s.buf, 0, s.capacity) };
|
||||
(v, s.requested)
|
||||
}
|
||||
|
||||
pub fn reuse(v: Vec<u8>, len: usize) -> RequestBuffer {
|
||||
let mut v = ManuallyDrop::new(v);
|
||||
v.reserve_exact(len.saturating_sub(len));
|
||||
RequestBuffer {
|
||||
buf: v.as_mut_ptr(),
|
||||
capacity: v.capacity(),
|
||||
requested: len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RequestBuffer {
|
||||
fn drop(&mut self) {
|
||||
unsafe { drop(Vec::from_raw_parts(self.buf, 0, self.capacity)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for RequestBuffer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("RequestBuffer")
|
||||
.field("requested", &self.requested)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl TransferRequest for RequestBuffer {
|
||||
type Response = Vec<u8>;
|
||||
}
|
||||
pub struct ResponseBuffer {
|
||||
pub(crate) buf: *mut u8,
|
||||
pub(crate) capacity: usize,
|
||||
pub(crate) transferred: usize,
|
||||
}
|
||||
|
||||
impl ResponseBuffer {
|
||||
pub(crate) fn from_vec(v: Vec<u8>, transferred: usize) -> ResponseBuffer {
|
||||
let mut v = ManuallyDrop::new(v);
|
||||
ResponseBuffer {
|
||||
buf: v.as_mut_ptr(),
|
||||
capacity: v.capacity(),
|
||||
transferred,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn actual_length(&self) -> usize {
|
||||
self.transferred
|
||||
}
|
||||
|
||||
pub fn reuse(self) -> Vec<u8> {
|
||||
let s = ManuallyDrop::new(self);
|
||||
unsafe { Vec::from_raw_parts(s.buf, 0, s.capacity) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for ResponseBuffer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("ResponseBuffer")
|
||||
.field("transferred", &self.transferred)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ResponseBuffer {
|
||||
fn drop(&mut self) {
|
||||
unsafe { drop(Vec::from_raw_parts(self.buf, 0, self.capacity)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TransferRequest for Vec<u8> {
|
||||
type Response = ResponseBuffer;
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
use super::{ResponseBuffer, TransferRequest};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[repr(u8)]
|
||||
pub enum Direction {
|
||||
|
|
@ -35,7 +37,7 @@ pub struct ControlOut<'a> {
|
|||
#[doc(alias = "bRequest")]
|
||||
pub request: u8,
|
||||
|
||||
#[doc(alias = "windex")]
|
||||
#[doc(alias = "wValue")]
|
||||
pub value: u16,
|
||||
|
||||
#[doc(alias = "wIndex")]
|
||||
|
|
@ -59,6 +61,10 @@ impl<'a> ControlOut<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl TransferRequest for ControlOut<'_> {
|
||||
type Response = ResponseBuffer;
|
||||
}
|
||||
|
||||
pub struct ControlIn {
|
||||
#[doc(alias = "bmRequestType")]
|
||||
pub control_type: ControlType,
|
||||
|
|
@ -117,3 +123,7 @@ fn pack_setup(
|
|||
(length >> 8) as u8,
|
||||
]
|
||||
}
|
||||
|
||||
impl TransferRequest for ControlIn {
|
||||
type Response = Vec<u8>;
|
||||
}
|
||||
|
|
@ -8,12 +8,9 @@ use std::{
|
|||
|
||||
use atomic_waker::AtomicWaker;
|
||||
|
||||
use crate::{
|
||||
control::{ControlIn, ControlOut},
|
||||
Completion,
|
||||
};
|
||||
use super::Completion;
|
||||
|
||||
pub(crate) trait PlatformTransfer: Send {
|
||||
pub trait PlatformTransfer: Send {
|
||||
/// Request cancellation of a transfer that may or may not currently be
|
||||
/// pending.
|
||||
fn cancel(&self);
|
||||
|
|
@ -23,7 +20,7 @@ pub trait TransferRequest {
|
|||
type Response;
|
||||
}
|
||||
|
||||
pub(crate) trait PlatformSubmit<D: TransferRequest>: PlatformTransfer {
|
||||
pub trait PlatformSubmit<D: TransferRequest>: PlatformTransfer {
|
||||
/// Fill the transfer with the data from `data` and submit it to the kernel.
|
||||
/// Arrange for `notify_completion(transfer)` to be called once the transfer
|
||||
/// has completed.
|
||||
|
|
@ -35,18 +32,6 @@ pub(crate) trait PlatformSubmit<D: TransferRequest>: PlatformTransfer {
|
|||
unsafe fn take_completed(&mut self) -> Completion<D::Response>;
|
||||
}
|
||||
|
||||
impl TransferRequest for Vec<u8> {
|
||||
type Response = Vec<u8>;
|
||||
}
|
||||
|
||||
impl TransferRequest for ControlIn {
|
||||
type Response = Vec<u8>;
|
||||
}
|
||||
|
||||
impl TransferRequest for ControlOut<'_> {
|
||||
type Response = usize;
|
||||
}
|
||||
|
||||
struct TransferInner<P: PlatformTransfer> {
|
||||
/// Platform-specific data.
|
||||
///
|
||||
|
|
@ -1,13 +1,23 @@
|
|||
use crate::{
|
||||
platform,
|
||||
transfer_internal::{PlatformSubmit, TransferHandle, TransferRequest},
|
||||
};
|
||||
use std::{
|
||||
future::Future,
|
||||
marker::PhantomData,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use crate::platform;
|
||||
|
||||
mod buffer;
|
||||
pub use buffer::{RequestBuffer, ResponseBuffer};
|
||||
|
||||
mod control;
|
||||
pub(crate) use control::SETUP_PACKET_SIZE;
|
||||
pub use control::{ControlIn, ControlOut, ControlType, Direction, Recipient};
|
||||
|
||||
mod internal;
|
||||
pub(crate) use internal::{
|
||||
notify_completion, PlatformSubmit, PlatformTransfer, TransferHandle, TransferRequest,
|
||||
};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum EndpointType {
|
||||
Control = 0,
|
||||
Loading…
Add table
Add a link
Reference in a new issue