Pre-release docs tweaks

This commit is contained in:
Kevin Mehall 2023-10-08 15:36:06 -06:00
parent efd9c3484f
commit 99dec9729d
9 changed files with 107 additions and 40 deletions

View file

@ -1,7 +1,9 @@
[package]
name = "nusb"
version = "0.1.0"
description = "Low-level access to USB devices in pure Rust"
description = "Cross-platform low-level access to USB devices in pure Rust"
categories = ["hardware-support"]
keywords = ["usb", "hardware"]
authors = ["Kevin Mehall <km@kevinmehall.net>"]
edition = "2021"
license = "Apache-2.0 OR MIT"

View file

@ -3,6 +3,8 @@ nusb
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
* Pure Rust, no dependency on libusb or any other C library.
@ -11,14 +13,13 @@ A new pure-Rust library for cross-platform low-level access to USB devices.
`futures_lite::block_on`.
* No context object. You just open a device. There is a global event loop thread
that is started when opening the first device.
* Doesn't try to paper over OS differences. For example, on Windows, you must open
a specific interface, not a device as a whole. `nusb`'s API makes working with interfaces
a required step so that it can map directly to Windows APIs.
* Thinner layer over OS APIs, with less internal state.
### :construction: Current status
* Linux: Control, bulk and interrupt transfers work, minimally tested
* Windows: Control, bulk and interrupt transfers work, minimally tested
* macOS : Not yet implemented
### License
MIT or Apache 2.0, at your option

View file

@ -8,7 +8,17 @@ use crate::{
/// An opened USB device.
///
/// Obtain a `Device` by calling [`DeviceInfo::open`].
/// Obtain a `Device` by calling [`DeviceInfo::open`]:
///
/// ```no_run
/// use nusb;
/// let device_info = nusb::list_devices().unwrap()
/// .find(|dev| dev.vendor_id() == 0xAAAA && dev.product_id() == 0xBBBB)
/// .expect("device not connected");
///
/// let device = device_info.open().expect("failed to open device");
/// let interface = device.claim_interface(0);
/// ```
///
/// This type is reference-counted with an [`Arc`] internally, and can be cloned cheaply for
/// use in multiple places in your program. The device is closed when all clones and all
@ -74,6 +84,27 @@ impl Interface {
}
/// Submit a single **IN (device-to-host)** transfer on the default **control** endpoint.
///
/// ### Example
///
/// ```no_run
/// use futures_lite::future::block_on;
/// use nusb::transfer::{ ControlIn, ControlType, Recipient };
/// # fn main() -> Result<(), std::io::Error> {
/// # let di = nusb::list_devices().unwrap().next().unwrap();
/// # let device = di.open().unwrap();
/// # let interface = device.claim_interface(0).unwrap();
///
/// let data: Vec<u8> = block_on(interface.control_in(ControlIn {
/// control_type: ControlType::Vendor,
/// recipient: Recipient::Device,
/// request: 0x30,
/// value: 0x0,
/// index: 0x0,
/// length: 64,
/// })).into_result()?;
/// # Ok(()) }
/// ```
pub fn control_in(&self, data: ControlIn) -> TransferFuture<ControlIn> {
let mut t = self.backend.make_transfer(0, EndpointType::Control);
t.submit::<ControlIn>(data);
@ -81,6 +112,27 @@ impl Interface {
}
/// Submit a single **OUT (host-to-device)** transfer on the default **control** endpoint.
///
/// ### Example
///
/// ```no_run
/// use futures_lite::future::block_on;
/// use nusb::transfer::{ ControlOut, ControlType, Recipient };
/// # fn main() -> Result<(), std::io::Error> {
/// # let di = nusb::list_devices().unwrap().next().unwrap();
/// # let device = di.open().unwrap();
/// # let interface = device.claim_interface(0).unwrap();
///
/// block_on(interface.control_out(ControlOut {
/// control_type: ControlType::Vendor,
/// recipient: Recipient::Device,
/// request: 0x32,
/// value: 0x0,
/// index: 0x0,
/// data: &[0x01, 0x02, 0x03, 0x04],
/// })).into_result()?;
/// # Ok(()) }
/// ```
pub fn control_out(&self, data: ControlOut) -> TransferFuture<ControlOut> {
let mut t = self.backend.make_transfer(0, EndpointType::Control);
t.submit::<ControlOut>(data);

View file

@ -32,10 +32,10 @@
//! device. To open an interface, call [`Device::claim_interface`]. Only one
//! program (or kernel driver) may claim an interface at a time.
//!
//! Use the resulting [`Interface`] struct to transfer data on the device's
//! control, bulk or interrupt endpoints. Transfers are async by default, and
//! can be awaited as individual `Future`s, or use a [`transfer::Queue`] to
//! manage streams of data.
//! Use the resulting [`Interface`] to transfer data on the device's control,
//! bulk or interrupt endpoints. Transfers are async by default, and can be
//! awaited as individual [`Future`][`transfer::TransferFuture`]s, or use a
//! [`Queue`][`transfer::Queue`] to manage streams of data.
//!
//! *For more details on how USB works, [USB in a
//! Nutshell](https://beyondlogic.org/usbnutshell/usb1.shtml) is a good
@ -44,10 +44,14 @@
//! ## Logging
//!
//! `nusb` uses the [`log`](https://docs.rs/log) crate to log debug and error
//! information. When submitting a bug report, please include the logs: include
//! a logging backend like [`env_logger`](https://docs.rs/env_logger) and
//! configure it to enable log output for this crate (for `env_logger` set
//! environment variable `RUST_LOG=nusb=debug`.)
//! information.
//!
//! When [submitting a bug report][gh-issues], please include the logs: use a
//! `log` backend like [`env_logger`](https://docs.rs/env_logger) and configure
//! it to enable log output for this crate (for `env_logger` set environment
//! variable `RUST_LOG=nusb=debug`.)
//!
//! [gh-issues]: https://github.com/kevinmehall/nusb/issues
//!
//! ## Platform support
//!
@ -78,7 +82,7 @@
//!
//! ### Windows
//!
//! `nusb` uses [SetupAPI] to find devices and [WinUSB] to access them.
//! `nusb` uses [WinUSB] on Windows.
//!
//! On Windows, devices are associated with a particular driver, which persists
//! across connections and reboots. Composite devices appear as multiple devices
@ -86,11 +90,11 @@
//! separate driver.
//!
//! To use `nusb`, your device or interface must be associated with the `WinUSB`
//! driver. The recommended way to this if you control the device firmware is to
//! use a [WCID] descriptor to tell Windows to install the WinUSB driver
//! automatically when the device is first connected. Alternatively [Zadig]
//! (GUI) or [libwdi] (CLI / C library) can be used to manually install the
//! WinUSB driver for a device.
//! driver. If you control the device firmware, the recommended way is to use a
//! [WCID] descriptor to tell Windows to install the WinUSB driver automatically
//! when the device is first connected. Alternatively [Zadig] (GUI) or [libwdi]
//! (CLI / C library) can be used to manually install the WinUSB driver for a
//! device.
//!
//! [SetupAPI]:
//! https://learn.microsoft.com/en-us/windows-hardware/drivers/install/setupapi

View file

@ -132,7 +132,10 @@ impl LinuxInterface {
}
pub fn set_alt_setting(&self, alt_setting: u8) -> Result<(), Error> {
debug!("Set interface {} alt setting to {alt_setting}", self.interface);
debug!(
"Set interface {} alt setting to {alt_setting}",
self.interface
);
Ok(usbfs::set_interface(
&self.device.fd,
self.interface,

View file

@ -1,5 +1,6 @@
//! Wrappers for the [usbfs] character device ioctls, translated from the
//! [C structures and ioctl definitions][uapi].
//!
//! [usbfs]: https://www.kernel.org/doc/html/latest/driver-api/usb/usb.html#the-usb-character-device-nodes
//! [uapi]: https://github.com/torvalds/linux/blob/master/tools/include/uapi/linux/usbdevice_fs.h
#![allow(dead_code)]

View file

@ -8,7 +8,9 @@ use std::{
use log::{debug, error};
use windows_sys::Win32::{
Devices::Usb::{WinUsb_Free, WinUsb_Initialize, WINUSB_INTERFACE_HANDLE, WinUsb_SetCurrentAlternateSetting},
Devices::Usb::{
WinUsb_Free, WinUsb_Initialize, WinUsb_SetCurrentAlternateSetting, WINUSB_INTERFACE_HANDLE,
},
Foundation::{FALSE, TRUE},
};

View file

@ -4,9 +4,11 @@
//! transfers or obtain a [`Queue`] to manage multiple transfers.
use std::{
fmt::Display,
future::Future,
io,
marker::PhantomData,
task::{Context, Poll}, io, fmt::Display,
task::{Context, Poll},
};
use crate::platform;

View file

@ -19,8 +19,8 @@ use super::{Completion, EndpointType, PlatformSubmit, TransferHandle, TransferRe
///
/// When the `Queue` is dropped, all pending transfers are cancelled.
///
/// ### Why use a `Queue` instead of submitting multiple transfers individually
/// with the methods on [`Interface`][`crate::Interface`]?
/// ### Why use a `Queue` instead of submitting multiple transfers individually with the methods on [`Interface`][`crate::Interface`]?
///
/// * Individual transfers give you individual `Future`s, which you then have
/// to keep track of and poll using something like `FuturesUnordered`.
/// * A `Queue` provides better cancellation semantics than `Future`'s