Skip to main content

esp_hal/usb/otg/
embassy_usb_device.rs

1//! USB OTG device driver for embassy-usb (Synopsys DWC).
2
3use embassy_usb_driver::{EndpointAddress, EndpointAllocError, EndpointType, Event, Unsupported};
4pub use embassy_usb_synopsys_otg::Config;
5use embassy_usb_synopsys_otg::{
6    Bus as OtgBus,
7    ControlPipe,
8    Driver as OtgDriver,
9    Endpoint,
10    In,
11    OtgInstance,
12    Out,
13    otg_v1::Otg,
14};
15
16use crate::usb::otg::Usb;
17
18/// Asynchronous USB driver.
19pub struct Driver<'d> {
20    inner: OtgDriver<'d>,
21    _usb: Usb<'d>,
22}
23
24impl<'d> Driver<'d> {
25    /// Initializes USB OTG for asynchronous device operation.
26    ///
27    /// # Arguments
28    ///
29    /// * `ep_out_buffer` - Buffer for received OUT packets. Must be large enough for all OUT
30    ///   endpoint max packet sizes.
31    pub fn new(peri: Usb<'d>, ep_out_buffer: &'d mut [u8], config: Config) -> Self {
32        let info = peri.info();
33        let instance = OtgInstance {
34            regs: unsafe { Otg::from_ptr(info.register_ptr.cast_mut()) },
35            state: peri.embassy_device_state(),
36            fifo_depth_words: info.fifo_depth_words as u16,
37            extra_rx_fifo_words: info.rx_fifo_extra_words,
38            phy_type: info.phy_type,
39            calculate_trdt_fn: |_| 5,
40        };
41        Self {
42            inner: OtgDriver::new(ep_out_buffer, instance, config),
43            _usb: peri,
44        }
45    }
46}
47
48impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> {
49    type EndpointOut = Endpoint<'d, Out>;
50    type EndpointIn = Endpoint<'d, In>;
51    type ControlPipe = ControlPipe<'d>;
52    type Bus = Bus<'d>;
53
54    fn alloc_endpoint_in(
55        &mut self,
56        ep_type: EndpointType,
57        ep_addr: Option<EndpointAddress>,
58        max_packet_size: u16,
59        interval_ms: u8,
60    ) -> Result<Self::EndpointIn, EndpointAllocError> {
61        self.inner
62            .alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)
63    }
64
65    fn alloc_endpoint_out(
66        &mut self,
67        ep_type: EndpointType,
68        ep_addr: Option<EndpointAddress>,
69        max_packet_size: u16,
70        interval_ms: u8,
71    ) -> Result<Self::EndpointOut, EndpointAllocError> {
72        self.inner
73            .alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)
74    }
75
76    fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
77        let (bus, cp) = self.inner.start(control_max_packet_size);
78
79        (
80            Bus {
81                inner: bus,
82                inited: false,
83                _usb: self._usb,
84            },
85            cp,
86        )
87    }
88}
89
90/// Asynchronous USB bus used internally by embassy-usb.
91pub struct Bus<'d> {
92    inner: OtgBus<'d>,
93    inited: bool,
94    _usb: Usb<'d>,
95}
96
97impl<'d> Bus<'d> {
98    fn init(&mut self) {
99        let i = self._usb.info();
100        (i.enable_device_mode)();
101
102        let r = unsafe { Otg::from_ptr(i.register_ptr.cast_mut()) };
103
104        self.inner.core_soft_reset();
105
106        self.inner.configure_as_device();
107        self.inner.config_v5();
108
109        r.pcgcctl().write(|w| w.0 = 0);
110
111        self._usb.bind_device_interrupt();
112    }
113
114    fn disable(&mut self) {
115        self._usb.disable_device_interrupt();
116        (self._usb.info().platform_bus_disable_on_drop)();
117        self.inited = false;
118    }
119}
120
121impl<'d> embassy_usb_driver::Bus for Bus<'d> {
122    async fn poll(&mut self) -> Event {
123        if !self.inited {
124            self.init();
125            self.inited = true;
126        }
127
128        self.inner.poll().await
129    }
130
131    fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) {
132        self.inner.endpoint_set_stalled(ep_addr, stalled)
133    }
134
135    fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool {
136        self.inner.endpoint_is_stalled(ep_addr)
137    }
138
139    fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) {
140        self.inner.endpoint_set_enabled(ep_addr, enabled)
141    }
142
143    async fn enable(&mut self) {
144        self.inner.enable().await
145    }
146
147    async fn disable(&mut self) {
148        self.inner.disable().await
149    }
150
151    async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
152        self.inner.remote_wakeup().await
153    }
154}
155
156impl<'d> Drop for Bus<'d> {
157    fn drop(&mut self) {
158        Bus::disable(self);
159    }
160}