Documentation
This commit is contained in:
parent
3a5f2812a9
commit
6878ad067c
4 changed files with 35 additions and 11 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue