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