Skip to main content

atsamd_hal/peripherals/usb/d11/
bus.rs

1// This crate uses standard host-centric USB terminology for transfer
2// directions. Therefore an OUT transfer refers to a host-to-device transfer,
3// and an IN transfer refers to a device-to-host transfer. This is mainly a
4// concern for implementing new USB peripheral drivers and USB classes, and
5// people doing that should be familiar with the USB standard. http://ww1.microchip.com/downloads/en/DeviceDoc/60001507E.pdf
6// http://ww1.microchip.com/downloads/en/AppNotes/Atmel-42261-SAM-D21-USB_Application-Note_AT06475.pdf
7
8use super::Descriptors;
9use crate::calibration::{usb_transn_cal, usb_transp_cal, usb_trim_cal};
10use crate::clock;
11use crate::gpio::{AlternateG, AnyPin, Pin, PA24, PA25};
12use crate::pac::usb::Device;
13use crate::pac::{Pm, Usb};
14use crate::usb::buffer::*;
15use crate::usb::devicedesc::DeviceDescBank;
16use atsamd_hal_macros::{hal_cfg, hal_macro_helper};
17use core::cell::{Ref, RefCell, RefMut};
18use core::marker::PhantomData;
19use critical_section::{Mutex, with as disable_interrupts};
20use usb_device::bus::PollResult;
21use usb_device::endpoint::{EndpointAddress, EndpointType};
22use usb_device::{Result as UsbResult, UsbDirection, UsbError};
23
24/// EndpointTypeBits represents valid values for the EPTYPE fields in
25/// the EPCFGn registers.
26#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
27pub enum EndpointTypeBits {
28    #[default]
29    Disabled = 0,
30    Control = 1,
31    Isochronous = 2,
32    Bulk = 3,
33    Interrupt = 4,
34    #[allow(unused)]
35    DualBank = 5,
36}
37
38impl From<EndpointType> for EndpointTypeBits {
39    fn from(ep_type: EndpointType) -> EndpointTypeBits {
40        match ep_type {
41            EndpointType::Control => EndpointTypeBits::Control,
42            EndpointType::Isochronous { .. } => EndpointTypeBits::Isochronous,
43            EndpointType::Bulk => EndpointTypeBits::Bulk,
44            EndpointType::Interrupt => EndpointTypeBits::Interrupt,
45        }
46    }
47}
48
49/// EPConfig tracks the desired configuration for one side of an endpoint.
50#[derive(Default, Clone, Copy)]
51struct EPConfig {
52    ep_type: EndpointTypeBits,
53    allocated_size: u16,
54    max_packet_size: u16,
55    addr: usize,
56}
57
58impl EPConfig {
59    fn new(
60        ep_type: EndpointType,
61        allocated_size: u16,
62        max_packet_size: u16,
63        buffer_addr: *mut u8,
64    ) -> Self {
65        Self {
66            ep_type: ep_type.into(),
67            allocated_size,
68            max_packet_size,
69            addr: buffer_addr as usize,
70        }
71    }
72}
73
74// EndpointInfo represents the desired configuration for an endpoint pair.
75#[derive(Default)]
76struct EndpointInfo {
77    bank0: EPConfig,
78    bank1: EPConfig,
79}
80
81impl EndpointInfo {
82    fn new() -> Self {
83        Default::default()
84    }
85}
86
87/// AllEndpoints tracks the desired configuration of all endpoints managed
88/// by the USB peripheral.
89struct AllEndpoints {
90    endpoints: [EndpointInfo; 8],
91}
92
93impl AllEndpoints {
94    fn new() -> Self {
95        Self {
96            endpoints: [
97                EndpointInfo::new(),
98                EndpointInfo::new(),
99                EndpointInfo::new(),
100                EndpointInfo::new(),
101                EndpointInfo::new(),
102                EndpointInfo::new(),
103                EndpointInfo::new(),
104                EndpointInfo::new(),
105            ],
106        }
107    }
108
109    fn find_free_endpoint(&self, dir: UsbDirection) -> UsbResult<usize> {
110        // start with 1 because 0 is reserved for Control
111        for idx in 1..8 {
112            let ep_type = match dir {
113                UsbDirection::Out => self.endpoints[idx].bank0.ep_type,
114                UsbDirection::In => self.endpoints[idx].bank1.ep_type,
115            };
116            if ep_type == EndpointTypeBits::Disabled {
117                return Ok(idx);
118            }
119        }
120        Err(UsbError::EndpointOverflow)
121    }
122
123    #[allow(clippy::too_many_arguments)]
124    fn allocate_endpoint(
125        &mut self,
126        dir: UsbDirection,
127        idx: usize,
128        ep_type: EndpointType,
129        allocated_size: u16,
130        max_packet_size: u16,
131        _interval: u8,
132        buffer_addr: *mut u8,
133    ) -> UsbResult<EndpointAddress> {
134        let bank = match dir {
135            UsbDirection::Out => &mut self.endpoints[idx].bank0,
136            UsbDirection::In => &mut self.endpoints[idx].bank1,
137        };
138        if bank.ep_type != EndpointTypeBits::Disabled {
139            return Err(UsbError::EndpointOverflow);
140        }
141
142        *bank = EPConfig::new(ep_type, allocated_size, max_packet_size, buffer_addr);
143
144        Ok(EndpointAddress::from_parts(idx, dir))
145    }
146}
147
148struct Inner {
149    desc: RefCell<Descriptors>,
150    _dm_pad: Pin<PA24, AlternateG>,
151    _dp_pad: Pin<PA25, AlternateG>,
152    endpoints: RefCell<AllEndpoints>,
153    buffers: RefCell<BufferAllocator>,
154}
155
156pub struct UsbBus {
157    inner: Mutex<RefCell<Inner>>,
158}
159
160struct Bank<'a, T> {
161    address: EndpointAddress,
162    usb: &'a Device,
163    desc: RefMut<'a, super::Descriptors>,
164    _phantom: PhantomData<T>,
165    endpoints: Ref<'a, AllEndpoints>,
166}
167
168impl<T> Bank<'_, T> {
169    fn usb(&self) -> &Device {
170        self.usb
171    }
172
173    #[inline]
174    fn index(&self) -> usize {
175        self.address.index()
176    }
177
178    #[inline]
179    fn config(&mut self) -> &EPConfig {
180        let ep = &self.endpoints.endpoints[self.address.index()];
181        if self.address.is_out() {
182            &ep.bank0
183        } else {
184            &ep.bank1
185        }
186    }
187}
188
189/// InBank represents In direction banks, Bank #1
190struct InBank;
191
192/// OutBank represents Out direction banks, Bank #0
193struct OutBank;
194
195impl Bank<'_, InBank> {
196    fn desc_bank(&mut self) -> &mut DeviceDescBank {
197        let idx = self.index();
198        self.desc.bank(idx, 1)
199    }
200
201    /// Returns true if Bank 1 is Ready and thus has data that can be written
202    #[inline]
203    fn is_ready(&self) -> bool {
204        self.usb().epstatus(self.index()).read().bk1rdy().bit()
205    }
206
207    /// Set Bank 1 Ready.
208    /// Ready means that the buffer contains data that can be sent.
209    #[inline]
210    fn set_ready(&self, ready: bool) {
211        if ready {
212            self.usb()
213                .epstatusset(self.index())
214                .write(|w| w.bk1rdy().set_bit());
215        } else {
216            self.usb()
217                .epstatusclr(self.index())
218                .write(|w| w.bk1rdy().set_bit());
219        }
220    }
221
222    /// Acknowledges the signal that the last packet was sent.
223    #[inline]
224    fn clear_transfer_complete(&self) {
225        // Clear bits in epintflag by writing them to 1
226        self.usb()
227            .epintflag(self.index())
228            .write(|w| w.trcpt1().set_bit().trfail1().set_bit());
229    }
230
231    /// Indicates if a transfer is complete or pending.
232    #[inline]
233    fn is_transfer_complete(&self) -> bool {
234        self.usb().epintflag(self.index()).read().trcpt1().bit()
235    }
236
237    /// Writes out endpoint configuration to its in-memory descriptor.
238    fn flush_config(&mut self) {
239        let config = *self.config();
240        {
241            let desc = self.desc_bank();
242            desc.set_address(config.addr as *mut u8);
243            desc.set_endpoint_size(config.max_packet_size);
244            desc.set_multi_packet_size(0);
245            desc.set_byte_count(0);
246        }
247    }
248
249    /// Enables endpoint-specific interrupts.
250    fn setup_ep_interrupts(&mut self) {
251        self.usb()
252            .epintenset(self.index())
253            .write(|w| w.trcpt1().set_bit());
254    }
255
256    /// Prepares to transfer a series of bytes by copying the data into the
257    /// bank1 buffer. The caller must call set_ready() to finalize the
258    /// transfer.
259    pub fn write(&mut self, buf: &[u8]) -> UsbResult<usize> {
260        let size = buf.len().min(self.config().allocated_size as usize);
261        let desc = self.desc_bank();
262
263        unsafe {
264            buf.as_ptr()
265                .copy_to_nonoverlapping(desc.get_address(), size);
266        }
267
268        desc.set_multi_packet_size(0);
269        desc.set_byte_count(size as u16);
270
271        Ok(size)
272    }
273
274    fn is_stalled(&self) -> bool {
275        self.usb().epintflag(self.index()).read().stall1().bit()
276    }
277
278    fn set_stall(&mut self, stall: bool) {
279        if stall {
280            self.usb()
281                .epstatusset(self.index())
282                .write(|w| w.stallrq1().set_bit())
283        } else {
284            self.usb()
285                .epstatusclr(self.index())
286                .write(|w| w.stallrq1().set_bit())
287        }
288    }
289}
290
291impl Bank<'_, OutBank> {
292    fn desc_bank(&mut self) -> &mut DeviceDescBank {
293        let idx = self.index();
294        self.desc.bank(idx, 0)
295    }
296
297    /// Returns true if Bank 0 is Ready and thus has data that can be read.
298    #[inline]
299    fn is_ready(&self) -> bool {
300        self.usb().epstatus(self.index()).read().bk0rdy().bit()
301    }
302
303    /// Set Bank 0 Ready.
304    /// Ready means that the buffer contains data that can be read.
305    #[inline]
306    fn set_ready(&self, ready: bool) {
307        if ready {
308            self.usb()
309                .epstatusset(self.index())
310                .write(|w| w.bk0rdy().set_bit());
311        } else {
312            self.usb()
313                .epstatusclr(self.index())
314                .write(|w| w.bk0rdy().set_bit());
315        }
316    }
317
318    /// Acknowledges the signal that data has been received.
319    #[inline]
320    fn clear_transfer_complete(&self) {
321        // Clear bits in epintflag by writing them to 1
322        self.usb()
323            .epintflag(self.index())
324            .write(|w| w.trcpt0().set_bit().trfail0().set_bit());
325    }
326
327    /// Returns true if a Received Setup interrupt has occurred.
328    /// This indicates that the read buffer holds a SETUP packet.
329    #[inline]
330    fn received_setup_interrupt(&self) -> bool {
331        self.usb().epintflag(self.index()).read().rxstp().bit()
332    }
333
334    /// Acknowledges the signal that a SETUP packet was received
335    /// successfully.
336    #[inline]
337    fn clear_received_setup_interrupt(&self) {
338        // Clear bits in epintflag by writing them to 1
339        self.usb()
340            .epintflag(self.index())
341            .write(|w| w.rxstp().set_bit());
342    }
343
344    /// Writes out endpoint configuration to its in-memory descriptor.
345    fn flush_config(&mut self) {
346        let config = *self.config();
347        {
348            let desc = self.desc_bank();
349            desc.set_address(config.addr as *mut u8);
350            desc.set_endpoint_size(config.max_packet_size);
351            desc.set_multi_packet_size(0);
352            desc.set_byte_count(0);
353        }
354    }
355
356    /// Enables endpoint-specific interrupts.
357    fn setup_ep_interrupts(&mut self) {
358        self.usb()
359            .epintenset(self.index())
360            .write(|w| w.rxstp().set_bit().trcpt0().set_bit());
361    }
362
363    /// Copies data from the bank0 buffer to the provided array. The caller
364    /// must call set_ready to indicate the buffer is free for the next
365    /// transfer.
366    pub fn read(&mut self, buf: &mut [u8]) -> UsbResult<usize> {
367        let desc = self.desc_bank();
368        let size = desc.get_byte_count() as usize;
369
370        if size > buf.len() {
371            return Err(UsbError::BufferOverflow);
372        }
373        unsafe {
374            desc.get_address()
375                .copy_to_nonoverlapping(buf.as_mut_ptr(), size);
376        }
377
378        desc.set_byte_count(0);
379        desc.set_multi_packet_size(0);
380
381        Ok(size)
382    }
383
384    fn is_stalled(&self) -> bool {
385        self.usb().epintflag(self.index()).read().stall0().bit()
386    }
387
388    fn set_stall(&mut self, stall: bool) {
389        if stall {
390            self.usb()
391                .epstatusset(self.index())
392                .write(|w| w.stallrq0().set_bit())
393        } else {
394            self.usb()
395                .epstatusclr(self.index())
396                .write(|w| w.stallrq0().set_bit())
397        }
398    }
399}
400
401impl Inner {
402    fn bank0(&'_ self, ep: EndpointAddress) -> UsbResult<Bank<'_, OutBank>> {
403        if ep.is_in() {
404            return Err(UsbError::InvalidEndpoint);
405        }
406        let endpoints = self.endpoints.borrow();
407
408        if endpoints.endpoints[ep.index()].bank0.ep_type == EndpointTypeBits::Disabled {
409            return Err(UsbError::InvalidEndpoint);
410        }
411        Ok(Bank {
412            address: ep,
413            usb: self.usb(),
414            desc: self.desc.borrow_mut(),
415            endpoints,
416            _phantom: PhantomData,
417        })
418    }
419
420    fn bank1(&'_ self, ep: EndpointAddress) -> UsbResult<Bank<'_, InBank>> {
421        if ep.is_out() {
422            return Err(UsbError::InvalidEndpoint);
423        }
424        let endpoints = self.endpoints.borrow();
425
426        if endpoints.endpoints[ep.index()].bank1.ep_type == EndpointTypeBits::Disabled {
427            return Err(UsbError::InvalidEndpoint);
428        }
429        Ok(Bank {
430            address: ep,
431            usb: self.usb(),
432            desc: self.desc.borrow_mut(),
433            endpoints,
434            _phantom: PhantomData,
435        })
436    }
437}
438
439impl UsbBus {
440    pub fn new(
441        _clock: &clock::UsbClock,
442        pm: &mut Pm,
443        dm_pad: impl AnyPin<Id = PA24>,
444        dp_pad: impl AnyPin<Id = PA25>,
445        _usb: Usb,
446    ) -> Self {
447        pm.apbbmask().modify(|_, w| w.usb_().set_bit());
448
449        let desc = RefCell::new(Descriptors::new());
450
451        let inner = Inner {
452            _dm_pad: dm_pad.into().into_mode::<AlternateG>(),
453            _dp_pad: dp_pad.into().into_mode::<AlternateG>(),
454            desc,
455            buffers: RefCell::new(BufferAllocator::default()),
456            endpoints: RefCell::new(AllEndpoints::new()),
457        };
458
459        Self {
460            inner: Mutex::new(RefCell::new(inner)),
461        }
462    }
463}
464
465impl Inner {
466    #[hal_cfg("usb-d11")]
467    fn usb(&self) -> &Device {
468        unsafe { (*Usb::ptr()).device() }
469    }
470
471    #[hal_cfg("usb-d21")]
472    fn usb(&self) -> &Device {
473        unsafe { (*Usb::ptr()).device() }
474    }
475
476    fn set_stall<EP: Into<EndpointAddress>>(&self, ep: EP, stall: bool) {
477        let ep = ep.into();
478        if ep.is_out() {
479            if let Ok(mut bank) = self.bank0(ep) {
480                bank.set_stall(stall);
481            }
482        } else if let Ok(mut bank) = self.bank1(ep) {
483            bank.set_stall(stall);
484        }
485    }
486}
487
488#[derive(Copy, Clone)]
489enum FlushConfigMode {
490    // Write configuration to all configured endpoints.
491    Full,
492    // Refresh configuration which was reset due to a bus reset.
493    ProtocolReset,
494}
495
496impl Inner {
497    #[hal_macro_helper]
498    fn enable(&mut self) {
499        let usb = self.usb();
500        usb.ctrla().modify(|_, w| w.swrst().set_bit());
501        while usb.syncbusy().read().swrst().bit_is_set() {}
502
503        let addr = self.desc.borrow().address();
504        usb.descadd().write(|w| unsafe { w.descadd().bits(addr) });
505        usb.padcal().modify(|_, w| unsafe {
506            w.transn().bits(usb_transn_cal());
507            w.transp().bits(usb_transp_cal());
508            w.trim().bits(usb_trim_cal())
509        });
510
511        #[hal_cfg("usb-d11")]
512        usb.qosctrl().modify(|_, w| unsafe {
513            w.dqos().bits(0b11);
514            w.cqos().bits(0b11)
515        });
516        #[hal_cfg("usb-d21")]
517        usb.qosctrl().modify(|_, w| unsafe {
518            w.dqos().bits(0b11);
519            w.cqos().bits(0b11)
520        });
521
522        usb.ctrla().modify(|_, w| {
523            w.mode().device();
524            w.runstdby().set_bit()
525        });
526        // full speed
527        usb.ctrlb().modify(|_, w| w.spdconf().fs());
528
529        usb.ctrla().modify(|_, w| w.enable().set_bit());
530        while usb.syncbusy().read().enable().bit_is_set() {}
531
532        // Clear pending.
533        usb.intflag()
534            .write(|w| unsafe { w.bits(usb.intflag().read().bits()) });
535        usb.intenset().write(|w| w.eorst().set_bit());
536
537        // Configure the endpoints before we attach, as hosts may enumerate
538        // before attempting a USB protocol reset.
539        self.flush_eps(FlushConfigMode::Full);
540
541        usb.ctrlb().modify(|_, w| w.detach().clear_bit());
542    }
543
544    /// Enables/disables the Start Of Frame (SOF) interrupt
545    fn sof_interrupt(&self, enable: bool) {
546        if enable {
547            self.usb().intenset().write(|w| w.sof().set_bit());
548        } else {
549            self.usb().intenclr().write(|w| w.sof().set_bit());
550        }
551    }
552
553    /// Configures all endpoints based on prior calls to alloc_ep().
554    fn flush_eps(&self, mode: FlushConfigMode) {
555        for idx in 0..8 {
556            match (mode, idx) {
557                // A flush due to a protocol reset need not reconfigure endpoint 0,
558                // except for enabling its interrupts.
559                (FlushConfigMode::ProtocolReset, 0) => {
560                    self.setup_ep_interrupts(EndpointAddress::from_parts(idx, UsbDirection::Out));
561                    self.setup_ep_interrupts(EndpointAddress::from_parts(idx, UsbDirection::In));
562                }
563                // A full flush configures all provisioned endpoints + enables interrupts.
564                // Endpoints 1-8 have identical behaviour when flushed due to protocol reset.
565                (FlushConfigMode::Full, _) | (FlushConfigMode::ProtocolReset, _) => {
566                    // Write bank configuration & endpoint type.
567                    self.flush_ep(idx);
568                    // Endpoint interrupts are configured after the write to EPTYPE, as it appears
569                    // writes to EPINTEN*[n] do not take effect unless the
570                    // endpoint is already somewhat configured. The datasheet is
571                    // ambiguous here, section 38.8.3.7 (Device Interrupt EndPoint Set n)
572                    // of the SAM D5x/E5x states:
573                    //    "This register is cleared by USB reset or when EPEN[n] is zero"
574                    // EPEN[n] is not a register that exists, nor does it align with any other
575                    // terminology. We assume this means setting EPCFG[n] to a
576                    // non-zero value, but we do interrupt configuration last to
577                    // be sure.
578                    self.setup_ep_interrupts(EndpointAddress::from_parts(idx, UsbDirection::Out));
579                    self.setup_ep_interrupts(EndpointAddress::from_parts(idx, UsbDirection::In));
580                }
581            }
582        }
583    }
584
585    /// flush_ep commits bank descriptor information for the endpoint pair,
586    /// and enables the endpoint according to its type.
587    fn flush_ep(&self, idx: usize) {
588        let cfg = self.usb().epcfg(idx);
589        let info = &self.endpoints.borrow().endpoints[idx];
590        // Write bank descriptors first. We do this so there is no period in
591        // which the endpoint is enabled but has an invalid descriptor.
592        if let Ok(mut bank) = self.bank0(EndpointAddress::from_parts(idx, UsbDirection::Out)) {
593            bank.flush_config();
594        }
595        if let Ok(mut bank) = self.bank1(EndpointAddress::from_parts(idx, UsbDirection::In)) {
596            bank.flush_config();
597        }
598
599        // Set the endpoint type. At this point, the endpoint is enabled.
600        cfg.modify(|_, w| unsafe {
601            w.eptype0()
602                .bits(info.bank0.ep_type as u8)
603                .eptype1()
604                .bits(info.bank1.ep_type as u8)
605        });
606    }
607
608    /// setup_ep_interrupts enables interrupts for the given endpoint address.
609    fn setup_ep_interrupts(&self, ep_addr: EndpointAddress) {
610        if ep_addr.is_out() {
611            if let Ok(mut bank) = self.bank0(ep_addr) {
612                bank.setup_ep_interrupts();
613            }
614        } else if let Ok(mut bank) = self.bank1(ep_addr) {
615            bank.setup_ep_interrupts();
616        }
617    }
618
619    /// protocol_reset is called by the USB HAL when it detects the host has
620    /// performed a USB reset.
621    fn protocol_reset(&self) {
622        self.flush_eps(FlushConfigMode::ProtocolReset);
623    }
624
625    fn suspend(&self) {}
626
627    fn resume(&self) {}
628
629    fn alloc_ep(
630        &mut self,
631        dir: UsbDirection,
632        addr: Option<EndpointAddress>,
633        ep_type: EndpointType,
634        max_packet_size: u16,
635        interval: u8,
636    ) -> UsbResult<EndpointAddress> {
637        // The USB hardware encodes the maximum packet size in 3 bits, so
638        // reserve enough buffer that the hardware won't overwrite it even if
639        // the other side issues an overly-long transfer.
640        let allocated_size = match max_packet_size {
641            1..=8 => 8,
642            9..=16 => 16,
643            17..=32 => 32,
644            33..=64 => 64,
645            65..=128 => 128,
646            129..=256 => 256,
647            257..=512 => 512,
648            513..=1023 => 1024,
649            _ => return Err(UsbError::Unsupported),
650        };
651
652        // packet size is too big to fit into an endpoint buffer
653        if allocated_size > ALLOC_SIZE_MAX_PER_EP as u16 {
654            return Err(UsbError::EndpointMemoryOverflow);
655        }
656
657        let buffer = self.buffers.borrow_mut().allocate_buffer()?;
658
659        let mut endpoints = self.endpoints.borrow_mut();
660
661        let idx = match addr {
662            None => endpoints.find_free_endpoint(dir)?,
663            Some(addr) => addr.index(),
664        };
665
666        let addr = endpoints.allocate_endpoint(
667            dir,
668            idx,
669            ep_type,
670            allocated_size,
671            max_packet_size,
672            interval,
673            buffer,
674        )?;
675
676        Ok(addr)
677    }
678
679    fn set_device_address(&self, addr: u8) {
680        self.usb()
681            .dadd()
682            .write(|w| unsafe { w.dadd().bits(addr).adden().set_bit() });
683    }
684
685    fn check_sof_interrupt(&self) -> bool {
686        if self.usb().intflag().read().sof().bit() {
687            self.usb().intflag().write(|w| w.sof().set_bit());
688            return true;
689        }
690        false
691    }
692
693    fn poll(&self) -> PollResult {
694        let intflags = self.usb().intflag().read();
695        if intflags.eorst().bit() {
696            // end of reset interrupt
697            self.usb().intflag().write(|w| w.eorst().set_bit());
698            return PollResult::Reset;
699        }
700        // As the suspend & wakup interrupts/states cannot distinguish between
701        // unconnected & unsuspended, we do not handle them to avoid spurious
702        // transitions.
703
704        let mut ep_out = 0;
705        let mut ep_in_complete = 0;
706        let mut ep_setup = 0;
707
708        let intbits = self.usb().epintsmry().read().bits();
709
710        for ep in 0..8u16 {
711            let mask = 1 << ep;
712
713            let idx = ep as usize;
714
715            if (intbits & mask) != 0 {
716                if let Ok(bank1) = self.bank1(EndpointAddress::from_parts(idx, UsbDirection::In)) {
717                    if bank1.is_transfer_complete() {
718                        bank1.clear_transfer_complete();
719                        ep_in_complete |= mask;
720                    }
721                }
722            }
723
724            // Can't test intbits, because bk0rdy doesn't interrupt
725            if let Ok(bank0) = self.bank0(EndpointAddress::from_parts(idx, UsbDirection::Out)) {
726                if bank0.received_setup_interrupt() {
727                    ep_setup |= mask;
728
729                    // The RXSTP interrupt is not cleared here, because doing so
730                    // would allow the USB hardware to overwrite the received
731                    // data, potentially before it is `read()` - see SAMD21
732                    // datasheet "32.6.2.6 Management of SETUP Transactions".
733                    // Setup events are only relevant for control endpoints, and
734                    // in typical USB devices, endpoint 0 is the only control
735                    // endpoint. The usb-device `poll()` method, which calls
736                    // this `poll()`, will immediately `read()` endpoint 0 when
737                    // its setup bit is set.
738                }
739
740                // Clear the transfer complete and transfer failed interrupt flags
741                // so that execution leaves the USB interrupt until the host makes
742                // another transaction.  The transfer failed flag may have been set
743                // if an OUT transaction wasn't read() from the endpoint by the
744                // Class; the hardware will have NAKed (unless the endpoint is
745                // isochronous) and the host may retry.
746                bank0.clear_transfer_complete();
747
748                // Use the bk0rdy flag via is_ready() to indicate that data has been
749                // received successfully, rather than the interrupting trcpt0 via
750                // is_transfer_ready(), because data may have been received on an
751                // earlier poll() which cleared trcpt0.  bk0rdy is cleared in the
752                // endpoint read().
753                if bank0.is_ready() {
754                    ep_out |= mask;
755                }
756            }
757        }
758
759        if ep_out == 0 && ep_in_complete == 0 && ep_setup == 0 {
760            PollResult::None
761        } else {
762            PollResult::Data {
763                ep_out,
764                ep_in_complete,
765                ep_setup,
766            }
767        }
768    }
769
770    fn write(&self, ep: EndpointAddress, buf: &[u8]) -> UsbResult<usize> {
771        let mut bank = self.bank1(ep)?;
772
773        if bank.is_ready() {
774            // Waiting for the host to pick up the existing data
775            return Err(UsbError::WouldBlock);
776        }
777
778        let size = bank.write(buf);
779
780        bank.clear_transfer_complete();
781        bank.set_ready(true); // ready to be sent
782
783        size
784    }
785
786    fn read(&self, ep: EndpointAddress, buf: &mut [u8]) -> UsbResult<usize> {
787        let mut bank = self.bank0(ep)?;
788        let rxstp = bank.received_setup_interrupt();
789
790        if bank.is_ready() || rxstp {
791            let size = bank.read(buf);
792
793            if rxstp {
794                bank.clear_received_setup_interrupt();
795            }
796
797            bank.clear_transfer_complete();
798            bank.set_ready(false);
799
800            size
801        } else {
802            Err(UsbError::WouldBlock)
803        }
804    }
805
806    fn is_stalled(&self, ep: EndpointAddress) -> bool {
807        if ep.is_out() {
808            self.bank0(ep).unwrap().is_stalled()
809        } else {
810            self.bank1(ep).unwrap().is_stalled()
811        }
812    }
813
814    fn set_stalled(&self, ep: EndpointAddress, stalled: bool) {
815        self.set_stall(ep, stalled);
816    }
817}
818
819impl UsbBus {
820    /// Enables the Start Of Frame (SOF) interrupt
821    pub fn enable_sof_interrupt(&self) {
822        disable_interrupts(|cs| self.inner.borrow(cs).borrow_mut().sof_interrupt(true))
823    }
824
825    /// Disables the Start Of Frame (SOF) interrupt
826    pub fn disable_sof_interrupt(&self) {
827        disable_interrupts(|cs| self.inner.borrow(cs).borrow_mut().sof_interrupt(false))
828    }
829
830    /// Checks, and clears if set, the Start Of Frame (SOF) interrupt flag
831    pub fn check_sof_interrupt(&self) -> bool {
832        disable_interrupts(|cs| self.inner.borrow(cs).borrow_mut().check_sof_interrupt())
833    }
834}
835
836impl usb_device::bus::UsbBus for UsbBus {
837    fn enable(&mut self) {
838        disable_interrupts(|cs| self.inner.borrow(cs).borrow_mut().enable())
839    }
840
841    fn reset(&self) {
842        disable_interrupts(|cs| self.inner.borrow(cs).borrow().protocol_reset())
843    }
844
845    fn suspend(&self) {
846        disable_interrupts(|cs| self.inner.borrow(cs).borrow().suspend())
847    }
848
849    fn resume(&self) {
850        disable_interrupts(|cs| self.inner.borrow(cs).borrow().resume())
851    }
852
853    fn alloc_ep(
854        &mut self,
855        dir: UsbDirection,
856        addr: Option<EndpointAddress>,
857        ep_type: EndpointType,
858        max_packet_size: u16,
859        interval: u8,
860    ) -> UsbResult<EndpointAddress> {
861        disable_interrupts(|cs| {
862            self.inner.borrow(cs).borrow_mut().alloc_ep(
863                dir,
864                addr,
865                ep_type,
866                max_packet_size,
867                interval,
868            )
869        })
870    }
871
872    fn set_device_address(&self, addr: u8) {
873        disable_interrupts(|cs| self.inner.borrow(cs).borrow().set_device_address(addr))
874    }
875
876    fn poll(&self) -> PollResult {
877        disable_interrupts(|cs| self.inner.borrow(cs).borrow().poll())
878    }
879
880    fn write(&self, ep: EndpointAddress, buf: &[u8]) -> UsbResult<usize> {
881        disable_interrupts(|cs| self.inner.borrow(cs).borrow().write(ep, buf))
882    }
883
884    fn read(&self, ep: EndpointAddress, buf: &mut [u8]) -> UsbResult<usize> {
885        disable_interrupts(|cs| self.inner.borrow(cs).borrow().read(ep, buf))
886    }
887
888    fn set_stalled(&self, ep: EndpointAddress, stalled: bool) {
889        disable_interrupts(|cs| self.inner.borrow(cs).borrow().set_stalled(ep, stalled))
890    }
891
892    fn is_stalled(&self, ep: EndpointAddress) -> bool {
893        disable_interrupts(|cs| self.inner.borrow(cs).borrow().is_stalled(ep))
894    }
895}