#[macro_use]
mod macros;
use bit_field::BitField;
use core::convert::TryInto;
use core::fmt;
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
pub const NUM_OF_ENDPOINT_CONTEXTS: usize = 31;
pub type Input32Byte = Input<8>;
pub type Input64Byte = Input<16>;
pub type InputControl32Byte = InputControl<8>;
pub type InputControl64Byte = InputControl<16>;
pub type Device32Byte = Device<8>;
pub type Device64Byte = Device<16>;
pub type Slot32Byte = Slot<8>;
pub type Slot64Byte = Slot<16>;
pub type Endpoint32Byte = Endpoint<8>;
pub type Endpoint64Byte = Endpoint<16>;
#[repr(C)]
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Input<const N: usize> {
control: InputControl<N>,
device: Device<N>,
}
impl_constructor!(Input, "Input");
impl<const N: usize> Input<N> {
const fn new() -> Self {
Self {
control: InputControl::new(),
device: Device::new(),
}
}
}
impl<const N: usize> InputHandler for Input<N> {
fn control(&self) -> &dyn InputControlHandler {
&self.control
}
fn control_mut(&mut self) -> &mut dyn InputControlHandler {
&mut self.control
}
fn device(&self) -> &dyn DeviceHandler {
&self.device
}
fn device_mut(&mut self) -> &mut dyn DeviceHandler {
&mut self.device
}
}
pub trait InputHandler {
fn control(&self) -> &dyn InputControlHandler;
fn control_mut(&mut self) -> &mut dyn InputControlHandler;
fn device(&self) -> &dyn DeviceHandler;
fn device_mut(&mut self) -> &mut dyn DeviceHandler;
}
#[repr(transparent)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct InputControl<const N: usize>([u32; N]);
impl_constructor!(InputControl, "Input Control");
impl<const N: usize> InputControl<N> {
const fn new() -> Self {
Self([0; N])
}
}
impl<const N: usize> AsRef<[u32]> for InputControl<N> {
fn as_ref(&self) -> &[u32] {
&self.0
}
}
impl<const N: usize> AsMut<[u32]> for InputControl<N> {
fn as_mut(&mut self) -> &mut [u32] {
&mut self.0
}
}
impl<const N: usize> InputControlHandler for InputControl<N> {}
impl<const N: usize> fmt::Debug for InputControl<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("InputControl")
.field("Drop Context flags", &self.0[0])
.field("Add Context flags", &self.0[1])
.field("configuration_value", &self.configuration_value())
.field("interface_number", &self.interface_number())
.field("alternate_setting", &self.alternate_setting())
.finish()
}
}
pub trait InputControlHandler: AsRef<[u32]> + AsMut<[u32]> {
#[must_use]
fn drop_context_flag(&self, i: usize) -> bool {
self.ensure_drop_context_index_within_range(i);
self.as_ref()[0].get_bit(i)
}
fn set_drop_context_flag(&mut self, i: usize) {
self.ensure_drop_context_index_within_range(i);
self.as_mut()[0].set_bit(i, true);
}
fn clear_drop_context_flag(&mut self, i: usize) {
self.ensure_drop_context_index_within_range(i);
self.as_mut()[0].set_bit(i, false);
}
#[must_use]
fn add_context_flag(&self, i: usize) -> bool {
self.ensure_add_context_index_within_range(i);
self.as_ref()[1].get_bit(i)
}
fn set_add_context_flag(&mut self, i: usize) {
self.ensure_add_context_index_within_range(i);
self.as_mut()[1].set_bit(i, true);
}
fn clear_add_context_flag(&mut self, i: usize) {
self.ensure_add_context_index_within_range(i);
self.as_mut()[1].set_bit(i, false);
}
rw_field_cx!([7](0..=7), configuration_value, "Configuration Value", u8);
rw_field_cx!([7](8..=15), interface_number, "Interface Number", u8);
rw_field_cx!([7](16..=23), alternate_setting, "Alternate Setting", u8);
#[doc(hidden)]
fn ensure_drop_context_index_within_range(&self, i: usize) {
assert!(
(2..=31).contains(&i),
"The index of Drop Context flag must be within 2..=31."
);
}
#[doc(hidden)]
fn ensure_add_context_index_within_range(&self, i: usize) {
assert!(
i <= 31,
"The index of Add Context flag must be less than 32."
);
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Device<const N: usize> {
slot: Slot<N>,
endpoints: [Endpoint<N>; NUM_OF_ENDPOINT_CONTEXTS],
}
impl_constructor!(Device, "Device");
impl<const N: usize> Device<N> {
const fn new() -> Self {
Self {
slot: Slot::new(),
endpoints: [Endpoint::new(); NUM_OF_ENDPOINT_CONTEXTS],
}
}
fn assert_dci(dci: usize) {
assert_ne!(
dci, 0,
"Call `DeviceHandler::slot` to get a handler of Slot Context.`"
);
assert!(dci <= 31, "DCI must be less than 32.");
}
}
impl<const N: usize> DeviceHandler for Device<N> {
fn slot(&self) -> &dyn SlotHandler {
&self.slot
}
fn slot_mut(&mut self) -> &mut dyn SlotHandler {
&mut self.slot
}
fn endpoint(&self, dci: usize) -> &dyn EndpointHandler {
Self::assert_dci(dci);
&self.endpoints[dci - 1]
}
fn endpoint_mut(&mut self, dci: usize) -> &mut dyn EndpointHandler {
Self::assert_dci(dci);
&mut self.endpoints[dci - 1]
}
}
pub trait DeviceHandler {
fn slot(&self) -> &dyn SlotHandler;
fn slot_mut(&mut self) -> &mut dyn SlotHandler;
fn endpoint(&self, dci: usize) -> &dyn EndpointHandler;
fn endpoint_mut(&mut self, dci: usize) -> &mut dyn EndpointHandler;
}
#[repr(transparent)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Slot<const N: usize>([u32; N]);
impl_constructor!(Slot, "Slot");
impl<const N: usize> Slot<N> {
const fn new() -> Self {
Self([0; N])
}
}
impl<const N: usize> AsRef<[u32]> for Slot<N> {
fn as_ref(&self) -> &[u32] {
&self.0
}
}
impl<const N: usize> AsMut<[u32]> for Slot<N> {
fn as_mut(&mut self) -> &mut [u32] {
&mut self.0
}
}
impl<const N: usize> SlotHandler for Slot<N> {}
impl_debug_from_methods_cx! {
Slot {
route_string,
speed,
multi_tt,
hub,
context_entries,
max_exit_latency,
root_hub_port_number,
number_of_ports,
parent_hub_slot_id,
parent_port_number,
tt_think_time,
interrupter_target,
usb_device_address,
slot_state,
}
}
pub trait SlotHandler: AsRef<[u32]> + AsMut<[u32]> {
rw_field_cx!([0](0..=19), route_string, "Route String", u32);
rw_field_cx!([0](20..=23), speed, "Speed", u8);
rw_bit_cx!([0](25), multi_tt, "Multi-TT");
rw_bit_cx!([0](26), hub, "Hub");
rw_field_cx!([0](27..=31), context_entries, "Context Entries", u8);
rw_field_cx!([1](0..=15), max_exit_latency, "Max Exit Latency", u16);
rw_field_cx!(
[1](16..=23),
root_hub_port_number,
"Root Hub Port Number",
u8
);
rw_field_cx!([1](24..=31), number_of_ports, "Number of Ports", u8);
rw_field_cx!([2](0..=7), parent_hub_slot_id, "Parent Hub Slot ID", u8);
rw_field_cx!([2](8..=15), parent_port_number, "Parent Port Number", u8);
rw_field_cx!([2](16..=17), tt_think_time, "TT Think Time", u8);
rw_field_cx!([2](22..=31), interrupter_target, "Interrupter Target", u16);
rw_field_cx!([3](0..=7), usb_device_address, "USB Device Address", u8);
#[must_use]
fn slot_state(&self) -> SlotState {
let v = self.as_ref()[3].get_bits(27..=31);
let s = FromPrimitive::from_u32(v);
s.expect("Slot State represents Reserved.")
}
fn set_slot_state(&mut self, state: SlotState) {
self.as_mut()[3].set_bits(27..=31, state as _);
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Endpoint<const N: usize>([u32; N]);
impl_constructor!(Endpoint, "Endpoint");
impl<const N: usize> Endpoint<N> {
const fn new() -> Self {
Self([0; N])
}
}
impl<const N: usize> AsRef<[u32]> for Endpoint<N> {
fn as_ref(&self) -> &[u32] {
&self.0
}
}
impl<const N: usize> AsMut<[u32]> for Endpoint<N> {
fn as_mut(&mut self) -> &mut [u32] {
&mut self.0
}
}
impl<const N: usize> EndpointHandler for Endpoint<N> {}
impl_debug_from_methods_cx! {
Endpoint {
endpoint_state,
mult,
max_primary_streams,
linear_stream_array,
interval,
max_endpoint_service_time_interval_payload_high,
error_count,
endpoint_type,
host_initiate_disable,
max_burst_size,
max_packet_size,
dequeue_cycle_state,
tr_dequeue_pointer,
average_trb_length,
max_endpoint_service_time_interval_payload_low,
}
}
pub trait EndpointHandler: AsRef<[u32]> + AsMut<[u32]> {
#[must_use]
fn endpoint_state(&self) -> EndpointState {
let v = self.as_ref()[0].get_bits(0..=2);
let s = FromPrimitive::from_u32(v);
s.expect("Endpoint State represents Reserved.")
}
fn set_endpoint_state(&mut self, s: EndpointState) {
self.as_mut()[0].set_bits(0..=2, s as _);
}
rw_field_cx!([0](8..=9), mult, "Mult", u8);
rw_field_cx!([0](10..=14), max_primary_streams, "Max Primary Streams", u8);
rw_bit_cx!([0](15), linear_stream_array, "Linear Stream Array");
rw_field_cx!([0](16..=23), interval, "Interval", u8);
rw_field_cx!(
[0](24..=31),
max_endpoint_service_time_interval_payload_high,
"Max Endpoint Service Time Interval Payload High",
u8
);
rw_field_cx!([1](1..=2), error_count, "Error Count", u8);
#[must_use]
fn endpoint_type(&self) -> EndpointType {
let v = self.as_ref()[1].get_bits(3..=5);
let t = FromPrimitive::from_u32(v);
t.expect("Invalid Endpoint Type.")
}
fn set_endpoint_type(&mut self, t: EndpointType) {
self.as_mut()[1].set_bits(3..=5, t as _);
}
rw_bit_cx!([1](7), host_initiate_disable, "Host Initiate Disable");
rw_field_cx!([1](8..=15), max_burst_size, "Max Burst Size", u8);
rw_field_cx!([1](16..=31), max_packet_size, "Max Packet Size", u16);
rw_bit_cx!([2](0), dequeue_cycle_state, "Dequeue Cycle State");
#[must_use]
fn tr_dequeue_pointer(&self) -> u64 {
let l: u64 = self.as_ref()[2].into();
let u: u64 = self.as_ref()[3].into();
(u << 32) | l
}
fn set_tr_dequeue_pointer(&mut self, a: u64) {
assert_eq!(a % 64, 0, "TR Dequeue Pointer must be 64-byte aligned.");
let l: u32 = a.get_bits(0..32).try_into().unwrap();
let u: u32 = a.get_bits(32..64).try_into().unwrap();
self.as_mut()[2] = l;
self.as_mut()[3] = u;
}
rw_field_cx!([4](0..=15), average_trb_length, "Average TRB Length", u16);
rw_field_cx!(
[4](16..=31),
max_endpoint_service_time_interval_payload_low,
"Max Endpoint Service Time Interval Payload Low",
u16
);
}
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)]
pub enum SlotState {
DisabledEnabled = 0,
Default = 1,
Addressed = 2,
Configured = 3,
}
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)]
pub enum EndpointState {
Disabled = 0,
Running = 1,
Halted = 2,
Stopped = 3,
Error = 4,
}
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)]
pub enum EndpointType {
NotValid = 0,
IsochOut = 1,
BulkOut = 2,
InterruptOut = 3,
Control = 4,
IsochIn = 5,
BulkIn = 6,
InterruptIn = 7,
}