1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
//! This crate defines a set of traits for use on the host side of the
//! USB.
//!
//! The `USBHost` defines the Host Controller Interface that can be
//! used by the `Driver` interface.
//!
//! The `Driver` interface defines the set of functions necessary to
//! use devices plugged into the host.
#![no_std]
pub mod descriptor;
pub mod setup;
pub use descriptor::*;
pub use setup::*;
/// Errors that can be generated when attempting to do a USB transfer.
#[derive(Debug)]
pub enum TransferError {
/// An error that may be retried.
Retry(&'static str),
/// A permanent error.
Permanent(&'static str),
}
/// Trait for host controller interface.
pub trait USBHost {
/// Issue a control transfer with an optional data stage to
/// `ep`. The data stage direction is determined by the direction
/// of `bm_request_type`.
///
/// On success, the amount of data transferred into `buf` is
/// returned.
fn control_transfer(
&mut self,
ep: &mut dyn Endpoint,
bm_request_type: RequestType,
b_request: RequestCode,
w_value: WValue,
w_index: u16,
buf: Option<&mut [u8]>,
) -> Result<usize, TransferError>;
/// Issue a transfer from `ep` to the host.
///
/// On success, the amount of data transferred into `buf` is
/// returned.
fn in_transfer(
&mut self,
ep: &mut dyn Endpoint,
buf: &mut [u8],
) -> Result<usize, TransferError>;
/// Issue a transfer from the host to `ep`.
///
/// On success, the amount of data transferred from `buf` is
/// returned. This should always be equal to `buf.len()`.
fn out_transfer(&mut self, ep: &mut dyn Endpoint, buf: &[u8]) -> Result<usize, TransferError>;
}
/// The type of transfer to use when talking to USB devices.
///
/// cf §9.6.6 of USB 2.0
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum TransferType {
Control = 0,
Isochronous = 1,
Bulk = 2,
Interrupt = 3,
}
/// The direction of the transfer with the USB device.
///
/// cf §9.6.6 of USB 2.0
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Direction {
Out,
In,
}
/// `Endpoint` defines the USB endpoint for various transfers.
pub trait Endpoint {
/// Address of the device owning this endpoint. Must be between 0
/// and 127.
fn address(&self) -> u8;
/// Endpoint number, irrespective of direction. (e.g., for both
/// endpoint addresses, `0x81` and `0x01`, this function would
/// return `0x01`).
fn endpoint_num(&self) -> u8;
/// The type of transfer this endpoint uses.
fn transfer_type(&self) -> TransferType;
/// The direction of transfer this endpoint accepts.
fn direction(&self) -> Direction;
/// The maximum packet size for this endpoint.
fn max_packet_size(&self) -> u16;
/// The data toggle sequence bit for the next transfer from the
/// device to the host.
fn in_toggle(&self) -> bool;
/// The `USBHost` will, when required, update the data toggle
/// sequence bit for the next device to host transfer.
fn set_in_toggle(&mut self, toggle: bool);
/// The data toggle sequence bit for the next transfer from the
/// host to the device.
fn out_toggle(&self) -> bool;
/// The `USBHost` will, when required, update the data toggle
/// sequence bit for the next host to device transfer.
fn set_out_toggle(&mut self, toggle: bool);
}
/// Types of errors that can be returned from a `Driver`.
#[derive(Copy, Clone, Debug)]
pub enum DriverError {
/// An error that may be retried.
Retry(u8, &'static str),
/// A permanent error.
Permanent(u8, &'static str),
}
/// Trait for drivers on the USB host.
pub trait Driver: core::fmt::Debug {
/// Does this driver want `device`?
///
/// Answering `true` to this not necessarily mean the driver will
/// get `device`.
fn want_device(&self, device: &DeviceDescriptor) -> bool;
/// Add `device` with address `address` to the driver's registry,
/// if necessary.
fn add_device(&mut self, device: DeviceDescriptor, address: u8) -> Result<(), DriverError>;
/// Remove the device at address `address` from the driver's
/// registry, if necessary.
fn remove_device(&mut self, address: u8);
/// Called regularly by the USB host to allow the driver to do any
/// work necessary on its registered devices.
///
/// `millis` is the current time, in milliseconds from some
/// arbitrary starting point. It should be expected that after a
/// long enough run-time, this value will wrap.
///
/// `usbhost` may be used for communication with the USB when
/// required.
fn tick(&mut self, millis: usize, usbhost: &mut dyn USBHost) -> Result<(), DriverError>;
}