Documentation

This commit is contained in:
Kevin Mehall 2023-11-07 21:31:53 -07:00
parent 3a5f2812a9
commit 6878ad067c
4 changed files with 35 additions and 11 deletions

View file

@ -5,7 +5,7 @@ A new pure-Rust library for cross-platform low-level access to USB devices.
[Documentation](https://docs.rs/nusb)
### Compared to [rusb](https://docs.rs/rusb/latest/rusb/) and libusb
### Compared to [rusb](https://docs.rs/rusb/latest/rusb/) and [libusb](https://libusb.info/)
* Pure Rust, no dependency on libusb or any other C library.
* Async-first, while not requiring an async runtime like `tokio` or
@ -19,7 +19,7 @@ A new pure-Rust library for cross-platform low-level access to USB devices.
* Linux: Control, bulk and interrupt transfers work, minimally tested
* Windows: Control, bulk and interrupt transfers work, minimally tested
* macOS : Not yet implemented
* macOS : [Not yet implemented](https://github.com/kevinmehall/nusb/issues/3)
### License
MIT or Apache 2.0, at your option

View file

@ -130,10 +130,12 @@ impl Device {
}
/// An opened interface of a USB device.
///
/// Obtain an `Interface` with the [`Device::claim_interface`] method.
///
/// This type is reference-counted with an [`Arc`] internally, and can be cloned cheaply for
/// use in multiple places in your program. The interface is released when all clones, and all
/// associated transfers ([`TransferFuture`]s and [`Queue`]s) are dropped.
/// associated [`TransferFuture`]s and [`Queue`]s are dropped.
#[derive(Clone)]
pub struct Interface {
backend: Arc<platform::Interface>,
@ -233,7 +235,7 @@ impl Interface {
/// Create a queue for managing multiple **OUT (device-to-host)** transfers on a **bulk** endpoint.
///
/// An OUT endpoint address must have the top (`0x80`) bit clear.
/// * An OUT endpoint address must have the top (`0x80`) bit clear.
pub fn bulk_out_queue(&self, endpoint: u8) -> Queue<Vec<u8>> {
Queue::new(self.backend.clone(), endpoint, EndpointType::Bulk)
}

View file

@ -125,9 +125,18 @@ impl TryFrom<Completion<ResponseBuffer>> for ResponseBuffer {
}
/// [`Future`] used to await the completion of a transfer.
///
/// Use the methods on [`Interface`][super::Interface] to
/// submit an individual transfer and obtain a `TransferFuture`.
///
/// The transfer is cancelled on drop. The buffer and
/// any partially-completed data are destroyed.
/// any partially-completed data are destroyed. This means
/// that `TransferFuture` is not [cancel-safe] and cannot be used
/// in `select!{}`, When racing a `TransferFuture` with a timeout
/// you cannot tell whether data may have been partially transferred on timeout.
/// Use the [`Queue`] interface if these matter for your application.
///
/// [cancel-safe]: https://docs.rs/tokio/latest/tokio/macro.select.html#cancellation-safety
pub struct TransferFuture<D: TransferRequest> {
transfer: TransferHandle<platform::TransferData>,
ty: PhantomData<D::Response>,

View file

@ -16,6 +16,8 @@ use super::{Completion, EndpointType, PlatformSubmit, TransferHandle, TransferRe
/// needs to attempt a transfer in every possible frame. That requires always
/// having a transfer request pending with the kernel by submitting multiple
/// transfer requests and re-submitting them as they complete.
///
/// Use the methods on [`Interface`][`crate::Interface`] to obtain a `Queue`.
///
/// When the `Queue` is dropped, all pending transfers are cancelled.
///
@ -25,18 +27,25 @@ use super::{Completion, EndpointType, PlatformSubmit, TransferHandle, TransferRe
/// to keep track of and poll using something like `FuturesUnordered`.
/// * A `Queue` provides better cancellation semantics than `Future`'s
/// cancel-on-drop.
/// * After dropping a `TransferFuture`, you lose the ability to get the
/// status of the cancelled transfer and see if it may have been partially
/// or fully completed.
/// * After dropping a [`TransferFuture`][super::TransferFuture], you lose
/// the ability to get the status of the cancelled transfer and see if it
/// may have been partially or fully completed.
/// * When cancelling multiple transfers, it's important to do so in reverse
/// order so that subsequent pending transfers can't end up executing.
/// When managing a collection of `TransferFuture`s it's tricky to
/// guarantee drop order, while `Queue` always cancels its contained
/// transfers in reverse order.
/// * The `TransferFuture` methods on `Interface` are not [cancel-safe],
/// meaning they cannot be used in `select!{}` or similar patterns,
/// because dropping the Future has side effects and can lose data. The
/// Future returned from [`Queue::next_complete`] is cancel-safe because
/// it merely waits for completion, while the `Queue` owns the pending
/// transfers.
/// * A queue caches the internal transfer data structures of the last
/// completed transfer, meaning that if you re-use the data buffer there is
/// no memory allocation involved in continued streaming.
///
/// [cancel-safe]: https://docs.rs/tokio/latest/tokio/macro.select.html#cancellation-safety
/// ### Example (read from an endpoint)
///
/// ```no_run
@ -151,6 +160,9 @@ where
/// For an `IN` endpoint, the completion contains a [`Vec<u8>`].\
/// For an `OUT` endpoint, the completion contains a [`ResponseBuffer`][`super::ResponseBuffer`].
///
/// This future is cancel-safe: it can be cancelled and re-created without
/// side effects, enabling its use in `select!{}` or similar.
///
/// Panics if there are no transfers pending.
pub fn next_complete<'a>(&'a mut self) -> impl Future<Output = Completion<R::Response>> + 'a {
poll_fn(|cx| {
@ -172,10 +184,11 @@ where
self.pending.len()
}
/// Cancel all pending transfers.
/// Request cancellation of all pending transfers.
///
/// They will still be returned from subsequent calls to `next_complete` so
/// you can tell which were completed, partially-completed, or cancelled.
/// The transfers will still be returned from subsequent calls to
/// `next_complete` so you can tell which were completed,
/// partially-completed, or cancelled.
pub fn cancel_all(&mut self) {
// Cancel transfers in reverse order to ensure subsequent transfers
// can't complete out of order while we're going through them.