aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib.rs
blob: 742e02c87ce3918ba2af71ea8bdac366fefeb213 (plain)
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
//! Traits for a hardware-agnostic USB host interface.

#![no_std]

mod descriptor;
mod setup;

pub use descriptor::*;
pub use setup::*;

#[derive(Debug)]
pub enum TransferError {
    Retry(&'static str),
    Permanent(&'static str),
}

pub trait USBHost {
    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>;

    fn in_transfer(
        &mut self,
        ep: &mut dyn Endpoint,
        buf: &mut [u8],
    ) -> Result<usize, TransferError>;

    fn out_transfer(&mut self, ep: &mut dyn Endpoint, buf: &[u8]) -> Result<usize, TransferError>;
}

// cf §9.6.6 of USB 2.0
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum TransferType {
    Control = 0,
    Isochronous = 1,
    Bulk = 2,
    Interrupt = 3,
}

// ibid
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Direction {
    Out,
    In,
}

pub trait Endpoint {
    fn address(&self) -> u8;

    fn endpoint_num(&self) -> u8;

    fn transfer_type(&self) -> TransferType;

    fn direction(&self) -> Direction;

    fn max_packet_size(&self) -> u16;

    fn in_toggle(&self) -> bool;

    fn set_in_toggle(&mut self, toggle: bool);

    fn out_toggle(&self) -> bool;

    fn set_out_toggle(&mut self, toggle: bool);
}

#[derive(Copy, Clone, Debug)]
pub enum DriverError {
    Retry(u8, &'static str),
    Permanent(u8, &'static str),
}
pub trait Driver: core::fmt::Debug {
    fn want_device(&self, device: &DeviceDescriptor) -> bool;

    fn add_device(&mut self, device: DeviceDescriptor, address: u8) -> Result<(), DriverError>;

    fn remove_device(&mut self, address: u8);

    fn tick(&mut self, millis: usize, usbhost: &mut dyn USBHost) -> Result<(), DriverError>;
}

// TODO: There needs to be a per-interface/function driver trait, as
// well, since that's how most drivers will actually work.
//
// As a result, the host driver has to at least get the full
// configuration.