usbh 0.1.0

Experimental host-side USB stack for embedded devices.
Documentation
use crate::bus::HostBus;
use crate::UsbHost;
use usb_device::UsbDirection;

pub struct Transfer {
    length: u16,
    state: TransferState,
}

enum TransferState {
    Control(UsbDirection, ControlState),
}

enum ControlState {
    WaitSetup,
    WaitData,
    WaitConfirm,
}

pub enum PollResult {
    ControlInComplete(u16),
    ControlOutComplete,
    Continue(Transfer),
}

impl Transfer {
    pub(crate) fn new_control_in(length: u16) -> Self {
        Self {
            length,
            state: TransferState::Control(UsbDirection::In, ControlState::WaitSetup),
        }
    }

    pub fn new_control_out(length: u16) -> Self {
        Self {
            length,
            state: TransferState::Control(UsbDirection::Out, ControlState::WaitSetup),
        }
    }

    pub(crate) fn stage_complete<B: HostBus>(self, host: &mut UsbHost<B>) -> PollResult {
        match self {
            Transfer {
                state: TransferState::Control(UsbDirection::In, control_state),
                length,
            } => match control_state {
                ControlState::WaitSetup => {
                    host.bus.write_data_in(length, true);
                    PollResult::Continue(Transfer {
                        state: TransferState::Control(UsbDirection::In, ControlState::WaitData),
                        length,
                    })
                }
                ControlState::WaitData => {
                    host.bus.write_data_out(&[]);
                    PollResult::Continue(Transfer {
                        state: TransferState::Control(UsbDirection::In, ControlState::WaitConfirm),
                        length,
                    })
                }
                ControlState::WaitConfirm => PollResult::ControlInComplete(length),
            },
            Transfer {
                state: TransferState::Control(UsbDirection::Out, control_state),
                length,
            } => match control_state {
                ControlState::WaitSetup => {
                    if length == 0 {
                        host.bus.write_data_in(0, true);
                        PollResult::Continue(Transfer {
                            state: TransferState::Control(
                                UsbDirection::Out,
                                ControlState::WaitConfirm,
                            ),
                            length,
                        })
                    } else {
                        host.bus.write_data_out_prepared();
                        PollResult::Continue(Transfer {
                            state: TransferState::Control(
                                UsbDirection::Out,
                                ControlState::WaitData,
                            ),
                            length,
                        })
                    }
                }
                ControlState::WaitData => {
                    host.bus.write_data_in(0, true);
                    PollResult::Continue(Transfer {
                        state: TransferState::Control(UsbDirection::Out, ControlState::WaitConfirm),
                        length,
                    })
                }
                ControlState::WaitConfirm => PollResult::ControlOutComplete,
            },
        }
    }
}