sam4l/usbc/
mod.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! SAM4L USB controller
6
7pub mod debug;
8
9#[allow(unused_imports)]
10use self::debug::{HexBuf, UdintFlags, UeconFlags, UestaFlags};
11use crate::pm;
12use crate::pm::{disable_clock, enable_clock, Clock, HSBClock, PBBClock};
13use crate::scif;
14use core::cell::Cell;
15use core::ptr;
16use core::slice;
17use kernel::debug as debugln;
18use kernel::hil;
19use kernel::hil::usb::TransferType;
20use kernel::utilities::cells::{OptionalCell, VolatileCell};
21use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
22use kernel::utilities::registers::{
23    register_bitfields, FieldValue, InMemoryRegister, LocalRegisterCopy, ReadOnly, ReadWrite,
24    WriteOnly,
25};
26use kernel::utilities::StaticRef;
27
28// The following macros provide some diagnostics and panics(!)
29// while this module is experimental and should eventually be removed or
30// replaced with better error handling.
31
32macro_rules! client_warn {
33    [ $( $arg:expr ),+ ] => {
34        debugln!($( $arg ),+)
35    };
36}
37
38macro_rules! client_err {
39    [ $( $arg:expr ),+ ] => {
40        panic!($( $arg ),+)
41    };
42}
43
44macro_rules! debug1 {
45    [ $( $arg:expr ),+ ] => {
46        {} // debugln!($( $arg ),+)
47    };
48}
49
50macro_rules! internal_err {
51    [ $( $arg:expr ),+ ] => {
52        panic!($( $arg ),+)
53    };
54}
55
56#[repr(C)]
57struct UsbcRegisters {
58    udcon: ReadWrite<u32, DeviceControl::Register>,
59    udint: ReadOnly<u32, DeviceInterrupt::Register>,
60    udintclr: WriteOnly<u32, DeviceInterrupt::Register>,
61    udintset: WriteOnly<u32, DeviceInterrupt::Register>,
62    udinte: ReadOnly<u32, DeviceInterrupt::Register>,
63    udinteclr: WriteOnly<u32, DeviceInterrupt::Register>,
64    udinteset: WriteOnly<u32, DeviceInterrupt::Register>,
65    uerst: ReadWrite<u32>,
66    udfnum: ReadOnly<u32>,
67    _reserved0: [u8; 0xdc], // 220 bytes
68    // Note that the SAM4L supports only 8 endpoints, but the registers
69    // are laid out such that there is room for 12.
70    // 0x100
71    uecfg: [ReadWrite<u32, EndpointConfig::Register>; 12],
72    uesta: [ReadOnly<u32, EndpointStatus::Register>; 12],
73    uestaclr: [WriteOnly<u32, EndpointStatus::Register>; 12],
74    uestaset: [WriteOnly<u32, EndpointStatus::Register>; 12],
75    uecon: [ReadOnly<u32, EndpointControl::Register>; 12],
76    ueconset: [WriteOnly<u32, EndpointControl::Register>; 12],
77    ueconclr: [WriteOnly<u32, EndpointControl::Register>; 12],
78    _reserved1: [u8; 0x1b0], // 432 bytes
79    // 0x400 = 1024
80    uhcon: ReadWrite<u32>,
81    uhint: ReadOnly<u32>,
82    uhintclr: WriteOnly<u32>,
83    uhintset: WriteOnly<u32>,
84    uhinte: ReadOnly<u32>,
85    uhinteclr: WriteOnly<u32>,
86    uhinteset: WriteOnly<u32>,
87    uprst: ReadWrite<u32>,
88    uhfnum: ReadWrite<u32>,
89    uhsofc: ReadWrite<u32>,
90    _reserved2: [u8; 0xd8], // 216 bytes
91    // 0x500 = 1280
92    upcfg: [ReadWrite<u32>; 12],
93    upsta: [ReadOnly<u32>; 12],
94    upstaclr: [WriteOnly<u32>; 12],
95    upstaset: [WriteOnly<u32>; 12],
96    upcon: [ReadOnly<u32>; 12],
97    upconset: [WriteOnly<u32>; 12],
98    upconclr: [WriteOnly<u32>; 12],
99    upinrq: [ReadWrite<u32>; 12],
100    _reserved3: [u8; 0x180], // 384 bytes
101    // 0x800 = 2048
102    usbcon: ReadWrite<u32, Control::Register>,
103    usbsta: ReadOnly<u32, Status::Register>,
104    usbstaclr: WriteOnly<u32>,
105    usbstaset: WriteOnly<u32>,
106    _reserved4: [u8; 8],
107    // 0x818
108    uvers: ReadOnly<u32>,
109    ufeatures: ReadOnly<u32>,
110    uaddrsize: ReadOnly<u32>,
111    uname1: ReadOnly<u32>,
112    uname2: ReadOnly<u32>,
113    usbfsm: ReadOnly<u32>,
114    udesc: ReadWrite<u32>,
115}
116
117register_bitfields![u32,
118    Control [
119        UIMOD OFFSET(25) NUMBITS(1) [
120            HostMode = 0,
121            DeviceMode = 1
122        ],
123        USBE OFFSET(15) NUMBITS(1) [],
124        FRZCLK OFFSET(14) NUMBITS(1) []
125    ],
126    Status [
127        SUSPEND OFFSET(16) NUMBITS(1) [],
128        CLKUSABLE OFFSET(14) NUMBITS(1) [],
129        SPEED OFFSET(12) NUMBITS(2) [
130            SpeedFull = 0b00,
131            SpeedLow = 0b10
132        ],
133        VBUSRQ OFFSET(9) NUMBITS(1) []
134    ],
135    DeviceControl [
136        GNAK OFFSET(17) NUMBITS(1) [],
137        LS OFFSET(12) NUMBITS(1) [
138            FullSpeed = 0,
139            LowSpeed = 1
140        ],
141        RMWKUP OFFSET(9) NUMBITS(1) [],
142        DETACH OFFSET(8) NUMBITS(1) [],
143        ADDEN OFFSET(7) NUMBITS(1) [],
144        UADD OFFSET(0) NUMBITS(7) []
145    ],
146    DeviceInterrupt [
147        EPINT OFFSET(12) NUMBITS(8),
148        UPRSM OFFSET(6) NUMBITS(1),
149        EORSM OFFSET(5) NUMBITS(1),
150        WAKEUP OFFSET(4) NUMBITS(1),
151        EORST OFFSET(3) NUMBITS(1),
152        SOF OFFSET(2) NUMBITS(1),
153        SUSP OFFSET(0) NUMBITS(1)
154    ],
155    EndpointConfig [
156        REPNB OFFSET(16) NUMBITS(4) [
157            NotRedirected = 0
158        ],
159        EPTYPE OFFSET(11) NUMBITS(2) [
160            Control = 0,
161            Isochronous = 1,
162            Bulk = 2,
163            Interrupt = 3
164        ],
165        EPDIR OFFSET(8) NUMBITS(1) [
166            Out = 0,
167            In = 1
168        ],
169        EPSIZE OFFSET(4) NUMBITS(3) [
170            Bytes8 = 0,
171            Bytes16 = 1,
172            Bytes32 = 2,
173            Bytes64 = 3,
174            Bytes128 = 4,
175            Bytes256 = 5,
176            Bytes512 = 6,
177            Bytes1024 = 7
178        ],
179        EPBK OFFSET(2) NUMBITS(1) [
180            Single = 0,
181            Double = 1
182        ]
183    ],
184    EndpointStatus [
185        CTRLDIR OFFSET(17) NUMBITS(1) [
186            Out = 0,
187            In = 1
188        ],
189        CURRBK OFFSET(14) NUMBITS(2) [
190            Bank0 = 0,
191            Bank1 = 1
192        ],
193        NBUSYBK OFFSET(12) NUMBITS(2) [],
194        RAMACER OFFSET(11) NUMBITS(1) [],
195        DTSEQ OFFSET(8) NUMBITS(2) [
196            Data0 = 0,
197            Data1 = 1
198        ],
199        STALLED OFFSET(6) NUMBITS(1) [],
200        CRCERR OFFSET(6) NUMBITS(1) [],
201        NAKIN OFFSET(4) NUMBITS(1) [],
202        NAKOUT OFFSET(3) NUMBITS(1) [],
203        ERRORF OFFSET(2) NUMBITS(1) [],
204        RXSTP OFFSET(2) NUMBITS(1) [],
205        RXOUT OFFSET(1) NUMBITS(1) [],
206        TXIN OFFSET(0) NUMBITS(1) []
207    ],
208    EndpointControl [
209        BUSY1E 25,
210        BUSY0E 24,
211        STALLRQ 19,
212        RSTDT 18,
213        FIFOCON 14,
214        KILLBK 13,
215        NBUSYBKE 12,
216        RAMACERE 11,
217        NREPLY 8,
218        STALLEDE 6,
219        CRCERRE 6,
220        NAKINE 4,
221        NAKOUTE 3,
222        RXSTPE 2,
223        ERRORFE 2,
224        RXOUTE 1,
225        TXINE 0
226    ]
227];
228
229const USBC_BASE: StaticRef<UsbcRegisters> =
230    unsafe { StaticRef::new(0x400A5000 as *const UsbcRegisters) };
231
232#[inline]
233fn usbc_regs() -> &'static UsbcRegisters {
234    &USBC_BASE
235}
236
237// Datastructures for tracking USB controller state
238
239pub const N_ENDPOINTS: usize = 8;
240
241// This ensures the `descriptors` field is laid out first
242#[repr(C)]
243// This provides the required alignment for the `descriptors` field
244#[repr(align(8))]
245pub struct Usbc<'a> {
246    descriptors: [Endpoint; N_ENDPOINTS],
247    state: OptionalCell<State>,
248    requests: [Cell<Requests>; N_ENDPOINTS],
249    client: OptionalCell<&'a dyn hil::usb::Client<'a>>,
250    pm: &'a pm::PowerManager,
251}
252
253#[derive(Copy, Clone, Default, Debug)]
254pub struct Requests {
255    pub resume_in: bool,
256    pub resume_out: bool,
257}
258
259impl Requests {
260    pub const fn new() -> Self {
261        Requests {
262            resume_in: false,
263            resume_out: false,
264        }
265    }
266}
267
268#[derive(Copy, Clone, Debug)]
269pub enum State {
270    // Controller disabled
271    Reset,
272
273    // Controller enabled, detached from bus
274    // (We may go to this state when the Host
275    // controller suspends the bus.)
276    Idle(Mode),
277
278    // Controller enabled, attached to bus
279    Active(Mode),
280}
281
282#[derive(Copy, Clone, Debug)]
283pub enum Mode {
284    Host,
285    Device {
286        speed: Speed,
287        config: DeviceConfig,
288        state: DeviceState,
289    },
290}
291
292type EndpointConfigValue = LocalRegisterCopy<u32, EndpointConfig::Register>;
293type EndpointStatusValue = LocalRegisterCopy<u32, EndpointStatus::Register>;
294
295#[derive(Copy, Clone, Debug, Default)]
296pub struct DeviceConfig {
297    pub endpoint_configs: [Option<EndpointConfigValue>; N_ENDPOINTS],
298}
299
300#[derive(Copy, Clone, Debug, Default)]
301pub struct DeviceState {
302    pub endpoint_states: [EndpointState; N_ENDPOINTS],
303}
304
305#[derive(Copy, Clone, Debug, Default)]
306pub enum EndpointState {
307    #[default]
308    Disabled,
309    Ctrl(CtrlState),
310    BulkIn(BulkInState),
311    BulkOut(BulkOutState),
312}
313
314#[derive(Copy, Clone, PartialEq, Debug)]
315pub enum CtrlState {
316    Init,
317    ReadIn,
318    ReadStatus,
319    WriteOut,
320    WriteStatus,
321    WriteStatusWait,
322    InDelay,
323}
324
325#[derive(Copy, Clone, PartialEq, Debug)]
326pub enum BulkInState {
327    Init,
328    Delay,
329}
330
331#[derive(Copy, Clone, PartialEq, Debug)]
332pub enum BulkOutState {
333    Init,
334    Delay,
335}
336
337#[derive(Copy, Clone, PartialEq, Debug)]
338pub enum Speed {
339    Full,
340    Low,
341}
342
343pub enum BankIndex {
344    Bank0,
345    Bank1,
346}
347
348impl From<BankIndex> for usize {
349    fn from(bi: BankIndex) -> usize {
350        match bi {
351            BankIndex::Bank0 => 0,
352            BankIndex::Bank1 => 1,
353        }
354    }
355}
356
357pub struct EndpointIndex(u8);
358
359impl EndpointIndex {
360    pub fn new(index: usize) -> EndpointIndex {
361        EndpointIndex(index as u8 & 0xf)
362    }
363
364    pub fn to_u32(self) -> u32 {
365        self.0 as u32
366    }
367}
368
369impl From<EndpointIndex> for usize {
370    fn from(ei: EndpointIndex) -> usize {
371        ei.0 as usize
372    }
373}
374
375pub type Endpoint = [Bank; 2];
376
377pub const fn new_endpoint() -> Endpoint {
378    [Bank::new(), Bank::new()]
379}
380
381#[repr(C)]
382pub struct Bank {
383    addr: VolatileCell<*mut u8>,
384
385    // The following fields are not actually registers
386    // (they may be placed anywhere in memory),
387    // but the register interface provides the volatile
388    // read/writes and bitfields that we need.
389    pub packet_size: InMemoryRegister<u32, PacketSize::Register>,
390    pub control_status: InMemoryRegister<u32, ControlStatus::Register>,
391
392    _reserved: u32,
393}
394
395impl Bank {
396    pub const fn new() -> Bank {
397        Bank {
398            addr: VolatileCell::new(ptr::null_mut()),
399            packet_size: InMemoryRegister::new(0),
400            control_status: InMemoryRegister::new(0),
401            _reserved: 0,
402        }
403    }
404
405    pub fn set_addr(&self, addr: *mut u8) {
406        self.addr.set(addr);
407    }
408}
409
410register_bitfields![u32,
411    PacketSize [
412        AUTO_ZLP OFFSET(31) NUMBITS(1) [
413            No = 0,
414            Yes = 1
415        ],
416        MULTI_PACKET_SIZE OFFSET(16) NUMBITS(15) [],
417        BYTE_COUNT OFFSET(0) NUMBITS(15) []
418    ],
419    ControlStatus [
420        UNDERF 18,
421        OVERF 17,
422        CRCERR 16,
423        STALLRQ_NEXT 0
424    ]
425];
426
427impl<'a> Usbc<'a> {
428    pub const fn new(pm: &'a pm::PowerManager) -> Self {
429        Usbc {
430            client: OptionalCell::empty(),
431            state: OptionalCell::new(State::Reset),
432            descriptors: [
433                new_endpoint(),
434                new_endpoint(),
435                new_endpoint(),
436                new_endpoint(),
437                new_endpoint(),
438                new_endpoint(),
439                new_endpoint(),
440                new_endpoint(),
441            ],
442            requests: [
443                Cell::new(Requests::new()),
444                Cell::new(Requests::new()),
445                Cell::new(Requests::new()),
446                Cell::new(Requests::new()),
447                Cell::new(Requests::new()),
448                Cell::new(Requests::new()),
449                Cell::new(Requests::new()),
450                Cell::new(Requests::new()),
451            ],
452            pm,
453        }
454    }
455
456    fn map_state<F, R>(&self, closure: F) -> R
457    where
458        F: FnOnce(&mut State) -> R,
459    {
460        let mut state = self.state.take().unwrap(); // Unwrap fail = map_state: state value is in use
461        let result = closure(&mut state);
462        self.state.set(state);
463        result
464    }
465
466    fn get_state(&self) -> State {
467        self.state.unwrap_or_panic() // Unwrap fail = get_state: state value is in use
468    }
469
470    fn set_state(&self, state: State) {
471        self.state.set(state);
472    }
473
474    /// Provide a buffer for transfers in and out of the given endpoint
475    /// (The controller need not be enabled before calling this method.)
476    fn endpoint_bank_set_buffer(
477        &self,
478        endpoint: EndpointIndex,
479        bank: BankIndex,
480        buf: &[VolatileCell<u8>],
481    ) {
482        let e: usize = From::from(endpoint);
483        let b: usize = From::from(bank);
484        let p = buf.as_ptr() as *const u8 as *mut u8;
485
486        debug1!("Set Endpoint{}/Bank{} addr={:8?}", e, b, p);
487        self.descriptors[e][b].set_addr(p);
488        self.descriptors[e][b].packet_size.write(
489            PacketSize::BYTE_COUNT.val(0)
490                + PacketSize::MULTI_PACKET_SIZE.val(0)
491                + PacketSize::AUTO_ZLP::No,
492        );
493    }
494
495    /// Enable the controller's clocks and interrupt and transition to Idle state
496    fn enable(&self, mode: Mode) {
497        match self.get_state() {
498            State::Reset => {
499                // Are the USBC clocks enabled at reset?
500                //   10.7.4 says no, but 17.5.3 says yes
501                // Also, "Being in Idle state does not require the USB clocks to
502                //   be activated" (17.6.2)
503                enable_clock(Clock::HSB(HSBClock::USBC));
504                enable_clock(Clock::PBB(PBBClock::USBC));
505
506                // If we got to this state via disable() instead of chip reset,
507                // the values USBCON.FRZCLK, USBCON.UIMOD, UDCON.LS have *not* been
508                // reset to their default values.
509
510                if let Mode::Device { speed, .. } = mode {
511                    usbc_regs().udcon.modify(match speed {
512                        Speed::Full => DeviceControl::LS::FullSpeed,
513                        Speed::Low => DeviceControl::LS::LowSpeed,
514                    });
515                }
516
517                // Enable in device mode
518                usbc_regs().usbcon.modify(Control::UIMOD::DeviceMode);
519                usbc_regs().usbcon.modify(Control::FRZCLK::CLEAR);
520                usbc_regs().usbcon.modify(Control::USBE::SET);
521
522                // Set the pointer to the endpoint descriptors
523                usbc_regs()
524                    .udesc
525                    .set(core::ptr::addr_of!(self.descriptors) as u32);
526
527                // Clear pending device global interrupts
528                usbc_regs().udintclr.write(
529                    DeviceInterrupt::SUSP::SET
530                        + DeviceInterrupt::SOF::SET
531                        + DeviceInterrupt::EORST::SET
532                        + DeviceInterrupt::EORSM::SET
533                        + DeviceInterrupt::UPRSM::SET,
534                );
535
536                // Enable device global interrupts
537                // Note: SOF has been omitted as it is not presently used,
538                // Note: SUSP has been omitted as SUSPEND/WAKEUP is not yet
539                //   implemented.
540                // Note: SOF and SUSP may nevertheless be enabled here
541                //   without harm, but it makes debugging easier to omit them.
542                usbc_regs().udinteset.write(
543                    DeviceInterrupt::EORST::SET
544                        + DeviceInterrupt::EORSM::SET
545                        + DeviceInterrupt::UPRSM::SET,
546                );
547
548                debug1!("Enabled");
549
550                self.set_state(State::Idle(mode));
551            }
552            _ => internal_err!("Already enabled"),
553        }
554    }
555
556    /// Disable the controller, its interrupt, and its clocks
557    fn _disable(&self) {
558        // Detach if necessary
559        if let State::Active(_) = self.get_state() {
560            self.detach();
561        }
562
563        // Disable USBC and its clocks
564        match self.get_state() {
565            State::Idle(..) => {
566                usbc_regs().usbcon.modify(Control::USBE::CLEAR);
567
568                disable_clock(Clock::PBB(PBBClock::USBC));
569                disable_clock(Clock::HSB(HSBClock::USBC));
570
571                self.set_state(State::Reset);
572            }
573            _ => internal_err!("Disable called from wrong state"),
574        }
575    }
576
577    /// Attach to the USB bus after enabling USB bus clock
578    fn attach(&self) {
579        match self.get_state() {
580            State::Idle(mode) => {
581                if self.pm.get_system_frequency() != 48000000 {
582                    internal_err!("The system clock does not support USB");
583                }
584
585                // XX: not clear that this always results in a usable USB clock
586                scif::generic_clock_enable(scif::GenericClock::GCLK7, scif::ClockSource::CLK_HSB);
587
588                while !usbc_regs().usbsta.is_set(Status::CLKUSABLE) {}
589
590                usbc_regs().udcon.modify(DeviceControl::DETACH::CLEAR);
591
592                debug1!("Attached");
593
594                self.set_state(State::Active(mode));
595            }
596            _ => internal_err!("Attach called in wrong state"),
597        }
598    }
599
600    /// Detach from the USB bus.  Also disable USB bus clock to save energy.
601    fn detach(&self) {
602        if let State::Active(mode) = self.get_state() {
603            usbc_regs().udcon.modify(DeviceControl::DETACH::SET);
604
605            scif::generic_clock_disable(scif::GenericClock::GCLK7);
606
607            self.set_state(State::Idle(mode));
608        }
609    }
610
611    /// Configure and enable an endpoint
612    fn endpoint_enable(&self, endpoint: usize, endpoint_config: EndpointConfigValue) {
613        self.endpoint_record_config(endpoint, endpoint_config);
614        self.endpoint_write_config(endpoint, endpoint_config);
615
616        // Enable the endpoint (meaning the controller will respond to requests
617        // to this endpoint)
618        usbc_regs()
619            .uerst
620            .set(usbc_regs().uerst.get() | (1 << endpoint));
621
622        self.endpoint_init(endpoint, endpoint_config);
623
624        // Set EPnINTE, enabling interrupts for this endpoint
625        usbc_regs().udinteset.set(1 << (12 + endpoint));
626
627        debug1!("Enabled endpoint {}", endpoint);
628    }
629
630    fn endpoint_record_config(&self, endpoint: usize, endpoint_config: EndpointConfigValue) {
631        // Record config in case of later bus reset
632        self.map_state(|state| match *state {
633            State::Reset => {
634                client_err!("Not enabled");
635            }
636            State::Idle(Mode::Device { ref mut config, .. }) => {
637                // The endpoint will be active when we next attach
638                config.endpoint_configs[endpoint] = Some(endpoint_config);
639            }
640            State::Active(Mode::Device { ref mut config, .. }) => {
641                // The endpoint will be active immediately
642                config.endpoint_configs[endpoint] = Some(endpoint_config);
643            }
644            _ => client_err!("Not in Device mode"),
645        });
646    }
647
648    fn endpoint_write_config(&self, endpoint: usize, config: EndpointConfigValue) {
649        // This must be performed after each bus reset
650
651        // Configure the endpoint
652        usbc_regs().uecfg[endpoint].set(From::from(config));
653
654        debug1!("Configured endpoint {}", endpoint);
655    }
656
657    fn endpoint_init(&self, endpoint: usize, config: EndpointConfigValue) {
658        self.map_state(|state| match *state {
659            State::Idle(Mode::Device { ref mut state, .. }) => {
660                self.endpoint_init_with_device_state(state, endpoint, config);
661            }
662            State::Active(Mode::Device { ref mut state, .. }) => {
663                self.endpoint_init_with_device_state(state, endpoint, config);
664            }
665            _ => internal_err!("Not reached"),
666        });
667    }
668
669    fn endpoint_init_with_device_state(
670        &self,
671        state: &mut DeviceState,
672        endpoint: usize,
673        config: EndpointConfigValue,
674    ) {
675        // This must be performed after each bus reset (see 17.6.2.2)
676
677        endpoint_enable_interrupts(
678            endpoint,
679            EndpointControl::RAMACERE::SET + EndpointControl::STALLEDE::SET,
680        );
681
682        if config.matches_all(EndpointConfig::EPTYPE::Control) {
683            endpoint_enable_interrupts(endpoint, EndpointControl::RXSTPE::SET);
684            state.endpoint_states[endpoint] = EndpointState::Ctrl(CtrlState::Init);
685        } else if config.matches_all(EndpointConfig::EPTYPE::Bulk + EndpointConfig::EPDIR::In) {
686            endpoint_enable_interrupts(endpoint, EndpointControl::TXINE::SET);
687            state.endpoint_states[endpoint] = EndpointState::BulkIn(BulkInState::Init);
688        } else if config.matches_all(EndpointConfig::EPTYPE::Bulk + EndpointConfig::EPDIR::Out) {
689            endpoint_enable_interrupts(endpoint, EndpointControl::RXOUTE::SET);
690            state.endpoint_states[endpoint] = EndpointState::BulkOut(BulkOutState::Init);
691        } else {
692            // Other endpoint types unimplemented
693        }
694
695        debug1!("Initialized endpoint {}", endpoint);
696    }
697
698    fn endpoint_resume_in(&self, endpoint: usize) {
699        self.map_state(|state| match *state {
700            State::Active(Mode::Device { ref mut state, .. }) => {
701                let endpoint_state = &mut state.endpoint_states[endpoint];
702                match *endpoint_state {
703                    EndpointState::BulkIn(BulkInState::Delay) => {
704                        // Return to Init state
705                        endpoint_enable_interrupts(endpoint, EndpointControl::TXINE::SET);
706                        *endpoint_state = EndpointState::BulkIn(BulkInState::Init);
707                    }
708                    // XXX: Add support for EndpointState::Interrupt*
709                    _ => debugln!("Ignoring superfluous resume_in"),
710                }
711            }
712            _ => debugln!("Ignoring inappropriate resume_in"),
713        });
714    }
715
716    fn endpoint_resume_out(&self, endpoint: usize) {
717        self.map_state(|state| match *state {
718            State::Active(Mode::Device { ref mut state, .. }) => {
719                let endpoint_state = &mut state.endpoint_states[endpoint];
720                match *endpoint_state {
721                    EndpointState::BulkOut(BulkOutState::Delay) => {
722                        // Return to Init state
723                        endpoint_enable_interrupts(endpoint, EndpointControl::RXOUTE::SET);
724                        *endpoint_state = EndpointState::BulkOut(BulkOutState::Init);
725                    }
726                    // XXX: Add support for EndpointState::Interrupt*
727                    _ => debugln!("Ignoring superfluous resume_out"),
728                }
729            }
730            _ => debugln!("Ignoring inappropriate resume_out"),
731        });
732    }
733
734    fn handle_requests(&self) {
735        for endpoint in 0..N_ENDPOINTS {
736            let mut requests = self.requests[endpoint].get();
737
738            if requests.resume_in {
739                self.endpoint_resume_in(endpoint);
740                requests.resume_in = false;
741            }
742            if requests.resume_out {
743                self.endpoint_resume_out(endpoint);
744                requests.resume_out = false;
745            }
746
747            self.requests[endpoint].set(requests);
748        }
749    }
750
751    /// Handle an interrupt from the USBC
752    pub fn handle_interrupt(&self) {
753        self.map_state(|state| match *state {
754            State::Reset => internal_err!("Received interrupt in Reset"),
755            State::Idle(_) => {
756                // We might process WAKEUP here
757                debug1!("Received interrupt in Idle");
758            }
759            State::Active(ref mut mode) => match *mode {
760                Mode::Device {
761                    speed,
762                    ref config,
763                    ref mut state,
764                } => self.handle_device_interrupt(speed, config, state),
765                Mode::Host => internal_err!("Host mode unimplemented"),
766            },
767        });
768
769        // Client callbacks invoked above may have generated state-changing requests
770        self.handle_requests();
771    }
772
773    /// Handle an interrupt while in device mode
774    fn handle_device_interrupt(
775        &self,
776        speed: Speed,
777        device_config: &DeviceConfig,
778        device_state: &mut DeviceState,
779    ) {
780        let udint = usbc_regs().udint.extract();
781
782        debug1!("--> UDINT={:?}", UdintFlags(udint.get()));
783
784        if udint.is_set(DeviceInterrupt::EORST) {
785            // Bus reset
786            debug1!("USB Bus Reset");
787
788            // Reconfigure what has been reset in the USBC
789            usbc_regs().udcon.modify(match speed {
790                Speed::Full => DeviceControl::LS::FullSpeed,
791                Speed::Low => DeviceControl::LS::LowSpeed,
792            });
793
794            // Reset our record of the device state
795            *device_state = DeviceState::default();
796
797            // Reconfigure and initialize endpoints
798            for i in 0..N_ENDPOINTS {
799                if let Some(endpoint_config) = device_config.endpoint_configs[i] {
800                    self.endpoint_write_config(i, endpoint_config);
801                    self.endpoint_init_with_device_state(device_state, i, endpoint_config);
802                }
803            }
804
805            // Alert the client
806            self.client.map(|client| {
807                client.bus_reset();
808            });
809
810            // Acknowledge the interrupt
811            usbc_regs().udintclr.write(DeviceInterrupt::EORST::SET);
812
813            // Wait for the next interrupt before doing anything else
814            return;
815        }
816
817        if udint.is_set(DeviceInterrupt::SUSP) {
818            // The transceiver has been suspended due to the bus being idle for 3ms.
819            // This condition is over when WAKEUP is set.
820
821            // "To further reduce power consumption it is recommended to freeze the USB
822            // clock by writing a one to the Freeze USB Clock (FRZCLK) bit in USBCON when
823            // the USB bus is in suspend mode.
824            //
825            // To recover from the suspend mode, the user shall wait for the Wakeup
826            // (WAKEUP) interrupt bit, which is set when a non-idle event is detected, and
827            // then write a zero to FRZCLK.
828            //
829            // As the WAKEUP interrupt bit in UDINT is set when a non-idle event is
830            // detected, it can occur regardless of whether the controller is in the
831            // suspend mode or not."
832
833            // Subscribe to WAKEUP
834            usbc_regs().udinteset.write(DeviceInterrupt::WAKEUP::SET);
835
836            // Acknowledge the "suspend" event
837            usbc_regs().udintclr.write(DeviceInterrupt::SUSP::SET);
838        }
839
840        if udint.is_set(DeviceInterrupt::WAKEUP) {
841            // XX: If we were suspended: Unfreeze the clock (and unsleep the MCU)
842
843            // Unsubscribe from WAKEUP
844            usbc_regs().udinteclr.write(DeviceInterrupt::WAKEUP::SET);
845
846            // Acknowledge the interrupt
847            usbc_regs().udintclr.write(DeviceInterrupt::WAKEUP::SET);
848
849            // Continue processing, as WAKEUP is usually set
850        }
851
852        if udint.is_set(DeviceInterrupt::SOF) {
853            // Acknowledge Start of frame
854            usbc_regs().udintclr.write(DeviceInterrupt::SOF::SET);
855        }
856
857        if udint.is_set(DeviceInterrupt::EORSM) {
858            // Controller received End of Resume
859            debug1!("UDINT EORSM");
860        }
861
862        if udint.is_set(DeviceInterrupt::UPRSM) {
863            // Controller sent Upstream Resume
864            debug1!("UDINT UPRSM");
865        }
866
867        // Process per-endpoint interrupt flags
868        for endpoint in 0..N_ENDPOINTS {
869            if udint.get() & (1 << (12 + endpoint)) == 0 {
870                // No interrupts for this endpoint
871                continue;
872            }
873
874            self.handle_endpoint_interrupt(endpoint, &mut device_state.endpoint_states[endpoint]);
875        }
876    }
877
878    fn handle_endpoint_interrupt(&self, endpoint: usize, endpoint_state: &mut EndpointState) {
879        let status = usbc_regs().uesta[endpoint].extract();
880        debug1!("  UESTA{}={:?}", endpoint, UestaFlags(status.get()));
881
882        if status.is_set(EndpointStatus::STALLED) {
883            debug1!("\tep{}: STALLED/CRCERR", endpoint);
884
885            // Acknowledge
886            usbc_regs().uestaclr[endpoint].write(EndpointStatus::STALLED::SET);
887        }
888
889        if status.is_set(EndpointStatus::RAMACER) {
890            debug1!("\tep{}: RAMACER", endpoint);
891
892            // Acknowledge
893            usbc_regs().uestaclr[endpoint].write(EndpointStatus::RAMACER::SET);
894        }
895
896        match *endpoint_state {
897            EndpointState::Ctrl(ref mut ctrl_state) => {
898                self.handle_ctrl_endpoint_interrupt(endpoint, ctrl_state, status)
899            }
900            EndpointState::BulkIn(ref mut bulk_in_state) => {
901                self.handle_bulk_in_endpoint_interrupt(endpoint, bulk_in_state, status)
902            }
903            EndpointState::BulkOut(ref mut bulk_out_state) => {
904                self.handle_bulk_out_endpoint_interrupt(endpoint, bulk_out_state, status)
905            }
906            EndpointState::Disabled => {
907                debug1!("Ignoring interrupt for disabled endpoint {}", endpoint);
908            }
909        }
910    }
911
912    fn handle_ctrl_endpoint_interrupt(
913        &self,
914        endpoint: usize,
915        ctrl_state: &mut CtrlState,
916        status: EndpointStatusValue,
917    ) {
918        let mut again = true;
919        while again {
920            again = false;
921            // `again` may be set to true below when it would be
922            // advantageous to process more flags without waiting for
923            // another interrupt.
924
925            debug1!(
926                "  ep{}: Ctrl({:?})  UECON={:?}",
927                endpoint,
928                *ctrl_state,
929                UeconFlags(usbc_regs().uecon[endpoint].get())
930            );
931
932            match *ctrl_state {
933                CtrlState::Init => {
934                    if status.is_set(EndpointStatus::RXSTP) {
935                        // We received a SETUP transaction
936
937                        debug1!("\tep{}: RXSTP", endpoint);
938                        // self.debug_show_d0();
939
940                        let bank = 0;
941                        let packet_bytes = self.descriptors[endpoint][bank]
942                            .packet_size
943                            .read(PacketSize::BYTE_COUNT);
944                        let result = if packet_bytes == 8 {
945                            self.client.map(|c| c.ctrl_setup(endpoint))
946                        } else {
947                            Some(hil::usb::CtrlSetupResult::ErrBadLength)
948                        };
949
950                        match result {
951                            Some(hil::usb::CtrlSetupResult::Ok)
952                            | Some(hil::usb::CtrlSetupResult::OkSetAddress) => {
953                                // Unsubscribe from SETUP interrupts
954                                endpoint_disable_interrupts(endpoint, EndpointControl::RXSTPE::SET);
955
956                                if status.matches_all(EndpointStatus::CTRLDIR::In) {
957                                    // The following Data stage will be IN
958
959                                    // Wait until bank is clear to send (TXIN).
960                                    // Also wait for NAKOUT to signal end of IN
961                                    // stage (the datasheet incorrectly says
962                                    // NAKIN).
963                                    usbc_regs().uestaclr[endpoint]
964                                        .write(EndpointStatus::NAKOUT::SET);
965                                    endpoint_enable_interrupts(
966                                        endpoint,
967                                        EndpointControl::TXINE::SET + EndpointControl::NAKOUTE::SET,
968                                    );
969                                    *ctrl_state = CtrlState::ReadIn;
970                                } else {
971                                    // The following Data stage will be OUT
972
973                                    // Wait for OUT packets (RXOUT).  Also wait
974                                    // for NAKIN to signal end of OUT stage.
975                                    usbc_regs().uestaclr[endpoint]
976                                        .write(EndpointStatus::NAKIN::SET);
977                                    endpoint_enable_interrupts(
978                                        endpoint,
979                                        EndpointControl::RXOUTE::SET + EndpointControl::NAKINE::SET,
980                                    );
981                                    *ctrl_state = CtrlState::WriteOut;
982                                }
983                            }
984                            failure => {
985                                // Respond with STALL to any following
986                                // transactions in this request
987                                usbc_regs().ueconset[endpoint].write(EndpointControl::STALLRQ::SET);
988
989                                match failure {
990                                    None => debug1!("\tep{}: No client to handle Setup", endpoint),
991                                    Some(_err) => {
992                                        debug1!("\tep{}: Client err on Setup: {:?}", endpoint, _err)
993                                    }
994                                }
995
996                                // Remain in Init state for next SETUP
997                            }
998                        }
999
1000                        // Acknowledge SETUP interrupt
1001                        usbc_regs().uestaclr[endpoint].write(EndpointStatus::RXSTP::SET);
1002                    }
1003                }
1004                CtrlState::ReadIn => {
1005                    // TODO: Handle Abort as described in 17.6.2.15
1006                    // (for Control and Isochronous only)
1007
1008                    if status.is_set(EndpointStatus::NAKOUT) {
1009                        // The host has completed the IN stage by sending an OUT token
1010
1011                        endpoint_disable_interrupts(
1012                            endpoint,
1013                            EndpointControl::TXINE::SET + EndpointControl::NAKOUTE::SET,
1014                        );
1015
1016                        debug1!("\tep{}: NAKOUT", endpoint);
1017                        self.client.map(|c| c.ctrl_status(endpoint));
1018
1019                        // Await end of Status stage
1020                        endpoint_enable_interrupts(endpoint, EndpointControl::RXOUTE::SET);
1021
1022                        // Acknowledge
1023                        usbc_regs().uestaclr[endpoint].write(EndpointStatus::NAKOUT::SET);
1024
1025                        *ctrl_state = CtrlState::ReadStatus;
1026
1027                        // Run handler again in case the RXOUT has already arrived
1028                        again = true;
1029                    } else if status.is_set(EndpointStatus::TXIN) {
1030                        // The data bank is ready to receive another IN payload
1031                        debug1!("\tep{}: TXIN", endpoint);
1032
1033                        let result = self.client.map(|c| {
1034                            // Allow client to write a packet payload to buffer
1035                            c.ctrl_in(endpoint)
1036                        });
1037                        match result {
1038                            Some(hil::usb::CtrlInResult::Packet(
1039                                packet_bytes,
1040                                transfer_complete,
1041                            )) => {
1042                                // Check if the entire buffer is full, and
1043                                // handle that case slightly differently. Note,
1044                                // this depends on the length of the buffer
1045                                // used. Right now, that is 64 bytes.
1046                                let packet_size = if packet_bytes == 64 && transfer_complete {
1047                                    // Send a complete final packet, and request
1048                                    // that the controller also send a zero-length
1049                                    // packet to signal the end of transfer
1050                                    PacketSize::BYTE_COUNT.val(64) + PacketSize::AUTO_ZLP::Yes
1051                                } else {
1052                                    // Send either a complete but not-final
1053                                    // packet, or a short and final packet (which
1054                                    // itself signals end of transfer)
1055                                    PacketSize::BYTE_COUNT.val(packet_bytes as u32)
1056                                };
1057                                let bank = 0;
1058                                self.descriptors[endpoint][bank]
1059                                    .packet_size
1060                                    .write(packet_size);
1061
1062                                debug1!(
1063                                    "\tep{}: Send CTRL IN packet ({} bytes)",
1064                                    endpoint,
1065                                    packet_bytes
1066                                );
1067                                // self.debug_show_d0();
1068
1069                                if transfer_complete {
1070                                    // IN data completely sent.  Unsubscribe from TXIN.
1071                                    // (Continue awaiting NAKOUT to indicate end of Data stage)
1072                                    endpoint_disable_interrupts(
1073                                        endpoint,
1074                                        EndpointControl::TXINE::SET,
1075                                    );
1076                                } else {
1077                                    // Continue waiting for next TXIN
1078                                }
1079
1080                                // Clear TXIN to signal to the controller that the IN payload is
1081                                // ready to send
1082                                usbc_regs().uestaclr[endpoint].write(EndpointStatus::TXIN::SET);
1083                            }
1084                            Some(hil::usb::CtrlInResult::Delay) => {
1085                                endpoint_disable_interrupts(endpoint, EndpointControl::TXINE::SET);
1086
1087                                debug1!("*** Client NAK");
1088
1089                                // XXX set busy bits?
1090
1091                                *ctrl_state = CtrlState::InDelay;
1092                            }
1093                            _ => {
1094                                // Respond with STALL to any following IN/OUT transactions
1095                                usbc_regs().ueconset[endpoint].write(EndpointControl::STALLRQ::SET);
1096
1097                                debug1!("\tep{}: Client IN err => STALL", endpoint);
1098
1099                                // Wait for next SETUP
1100                                endpoint_disable_interrupts(
1101                                    endpoint,
1102                                    EndpointControl::NAKOUTE::SET,
1103                                );
1104                                endpoint_enable_interrupts(endpoint, EndpointControl::RXSTPE::SET);
1105                                *ctrl_state = CtrlState::Init;
1106                            }
1107                        }
1108                    }
1109                }
1110                CtrlState::ReadStatus => {
1111                    if status.is_set(EndpointStatus::RXOUT) {
1112                        // Host has completed Status stage by sending an OUT packet
1113
1114                        debug1!("\tep{}: RXOUT: End of Control Read transaction", endpoint);
1115
1116                        // Wait for next SETUP
1117                        endpoint_disable_interrupts(endpoint, EndpointControl::RXOUTE::SET);
1118                        endpoint_enable_interrupts(endpoint, EndpointControl::RXSTPE::SET);
1119                        *ctrl_state = CtrlState::Init;
1120
1121                        // Acknowledge
1122                        usbc_regs().uestaclr[endpoint].write(EndpointStatus::RXOUT::SET);
1123
1124                        self.client.map(|c| c.ctrl_status_complete(endpoint));
1125                    }
1126                }
1127                CtrlState::WriteOut => {
1128                    if status.is_set(EndpointStatus::RXOUT) {
1129                        // Received data
1130
1131                        debug1!("\tep{}: RXOUT: Received Control Write data", endpoint);
1132                        // self.debug_show_d0();
1133
1134                        // Pass the data to the client and see how it reacts
1135                        let bank = 0;
1136                        let result = self.client.map(|c| {
1137                            c.ctrl_out(
1138                                endpoint,
1139                                self.descriptors[endpoint][bank]
1140                                    .packet_size
1141                                    .read(PacketSize::BYTE_COUNT),
1142                            )
1143                        });
1144                        match result {
1145                            Some(hil::usb::CtrlOutResult::Ok) => {
1146                                // Acknowledge
1147                                usbc_regs().uestaclr[endpoint].write(EndpointStatus::RXOUT::SET);
1148                            }
1149                            Some(hil::usb::CtrlOutResult::Delay) => {
1150                                // Don't acknowledge; hardware will have to send NAK
1151
1152                                // Unsubscribe from RXOUT until client says it is ready
1153                                // (But there is not yet any interface for that)
1154                                endpoint_disable_interrupts(endpoint, EndpointControl::RXOUTE::SET);
1155                            }
1156                            _ => {
1157                                // Respond with STALL to any following transactions
1158                                // in this request
1159                                usbc_regs().ueconset[endpoint].write(EndpointControl::STALLRQ::SET);
1160
1161                                debug1!("\tep{}: Client OUT err => STALL", endpoint);
1162
1163                                // Wait for next SETUP
1164                                endpoint_disable_interrupts(
1165                                    endpoint,
1166                                    EndpointControl::RXOUTE::SET + EndpointControl::NAKINE::SET,
1167                                );
1168                                endpoint_enable_interrupts(endpoint, EndpointControl::RXSTPE::SET);
1169                                *ctrl_state = CtrlState::Init;
1170                            }
1171                        }
1172                    }
1173                    if status.is_set(EndpointStatus::NAKIN) {
1174                        // The host has completed the Data stage by sending an IN token
1175                        debug1!("\tep{}: NAKIN: Control Write -> Status stage", endpoint);
1176
1177                        // Acknowledge
1178                        usbc_regs().uestaclr[endpoint].write(EndpointStatus::NAKIN::SET);
1179
1180                        // Wait for bank to be free so we can write ZLP to acknowledge transfer
1181                        endpoint_disable_interrupts(
1182                            endpoint,
1183                            EndpointControl::RXOUTE::SET + EndpointControl::NAKINE::SET,
1184                        );
1185                        endpoint_enable_interrupts(endpoint, EndpointControl::TXINE::SET);
1186                        *ctrl_state = CtrlState::WriteStatus;
1187
1188                        // Can probably send the ZLP immediately
1189                        again = true;
1190                    }
1191                }
1192                CtrlState::WriteStatus => {
1193                    if status.is_set(EndpointStatus::TXIN) {
1194                        debug1!(
1195                            "\tep{}: TXIN for Control Write Status (will send ZLP)",
1196                            endpoint
1197                        );
1198
1199                        self.client.map(|c| c.ctrl_status(endpoint));
1200
1201                        // Send zero-length packet to acknowledge transaction
1202                        let bank = 0;
1203                        self.descriptors[endpoint][bank]
1204                            .packet_size
1205                            .write(PacketSize::BYTE_COUNT.val(0));
1206
1207                        // Signal to the controller that the IN payload is ready to send
1208                        usbc_regs().uestaclr[endpoint].write(EndpointStatus::TXIN::SET);
1209
1210                        // Wait for TXIN again to confirm that IN payload has been sent
1211                        *ctrl_state = CtrlState::WriteStatusWait;
1212                    }
1213                }
1214                CtrlState::WriteStatusWait => {
1215                    if status.is_set(EndpointStatus::TXIN) {
1216                        debug1!("\tep{}: TXIN: Control Write Status Complete", endpoint);
1217
1218                        // Wait for next SETUP
1219                        endpoint_disable_interrupts(endpoint, EndpointControl::TXINE::SET);
1220                        endpoint_enable_interrupts(endpoint, EndpointControl::RXSTPE::SET);
1221                        *ctrl_state = CtrlState::Init;
1222
1223                        // for SetAddress, client must enable address after STATUS stage
1224                        self.client.map(|c| c.ctrl_status_complete(endpoint));
1225                    }
1226                }
1227                CtrlState::InDelay => internal_err!("Not reached"),
1228            }
1229
1230            // Uncomment the following line to run the above while loop only once per interrupt,
1231            // which can make debugging easier.
1232            //
1233            // again = false;
1234        }
1235    }
1236
1237    fn handle_bulk_out_endpoint_interrupt(
1238        &self,
1239        endpoint: usize,
1240        bulk_out_state: &mut BulkOutState,
1241        status: EndpointStatusValue,
1242    ) {
1243        match *bulk_out_state {
1244            BulkOutState::Init => {
1245                if status.is_set(EndpointStatus::RXOUT) {
1246                    // We got an OUT request from the host
1247
1248                    debug1!("\tep{}: RXOUT", endpoint);
1249
1250                    if !usbc_regs().uecon[endpoint].is_set(EndpointControl::FIFOCON) {
1251                        debugln!("Got RXOUT but not FIFOCON");
1252                        return;
1253                    }
1254                    // A bank is full of an OUT packet
1255
1256                    let bank = 0;
1257                    let packet_bytes = self.descriptors[endpoint][bank]
1258                        .packet_size
1259                        .read(PacketSize::BYTE_COUNT);
1260
1261                    let result = self.client.map(|c| {
1262                        // Allow client to consume the packet
1263                        c.packet_out(TransferType::Bulk, endpoint, packet_bytes)
1264                    });
1265                    match result {
1266                        Some(hil::usb::OutResult::Ok) => {
1267                            // Acknowledge
1268                            usbc_regs().uestaclr[endpoint].write(EndpointStatus::RXOUT::SET);
1269
1270                            // Clear FIFOCON to signal that the packet was consumed
1271                            usbc_regs().ueconclr[endpoint].write(EndpointControl::FIFOCON::SET);
1272
1273                            debug1!(
1274                                "\tep{}: Recv BULK OUT packet ({} bytes)",
1275                                endpoint,
1276                                packet_bytes
1277                            );
1278
1279                            // Remain in Init state
1280                        }
1281                        Some(hil::usb::OutResult::Delay) => {
1282                            // The client is not ready to consume data; wait for resume
1283
1284                            endpoint_disable_interrupts(endpoint, EndpointControl::RXOUTE::SET);
1285
1286                            *bulk_out_state = BulkOutState::Delay;
1287                        }
1288                        _ => {
1289                            debug1!("\tep{}: Client OUT err => STALL", endpoint);
1290
1291                            // Respond with STALL to any following IN/OUT transactions
1292                            usbc_regs().ueconset[endpoint].write(EndpointControl::STALLRQ::SET);
1293
1294                            // XXX: interrupts?
1295
1296                            // Remain in Init state?
1297                        }
1298                    }
1299                }
1300            }
1301            BulkOutState::Delay => internal_err!("Not reached"),
1302        }
1303    }
1304
1305    fn handle_bulk_in_endpoint_interrupt(
1306        &self,
1307        endpoint: usize,
1308        bulk_in_state: &mut BulkInState,
1309        status: EndpointStatusValue,
1310    ) {
1311        match *bulk_in_state {
1312            BulkInState::Init => {
1313                if status.is_set(EndpointStatus::TXIN) {
1314                    // We got an IN request from the host
1315
1316                    debug1!("\tep{}: TXIN", endpoint);
1317
1318                    if !usbc_regs().uecon[endpoint].is_set(EndpointControl::FIFOCON) {
1319                        debugln!("Got TXIN but not FIFOCON");
1320                        return;
1321                    }
1322                    // A bank is free to write an IN packet
1323
1324                    let result = self.client.map(|c| {
1325                        // Allow client to write a packet payload to the buffer
1326                        c.packet_in(TransferType::Bulk, endpoint)
1327                    });
1328                    match result {
1329                        Some(hil::usb::InResult::Packet(packet_bytes)) => {
1330                            // Acknowledge
1331                            usbc_regs().uestaclr[endpoint].write(EndpointStatus::TXIN::SET);
1332
1333                            // Tell the controller the size of the packet
1334                            let bank = 0;
1335                            self.descriptors[endpoint][bank]
1336                                .packet_size
1337                                .write(PacketSize::BYTE_COUNT.val(packet_bytes as u32));
1338
1339                            // Clear FIFOCON to signal data ready to send
1340                            usbc_regs().ueconclr[endpoint].write(EndpointControl::FIFOCON::SET);
1341
1342                            debug1!(
1343                                "\tep{}: Send BULK IN packet ({} bytes)",
1344                                endpoint,
1345                                packet_bytes
1346                            );
1347
1348                            // Remain in Init state
1349                        }
1350                        Some(hil::usb::InResult::Delay) => {
1351                            // The client is not ready to send data; wait for resume
1352
1353                            endpoint_disable_interrupts(endpoint, EndpointControl::TXINE::SET);
1354
1355                            *bulk_in_state = BulkInState::Delay;
1356                        }
1357                        _ => {
1358                            debug1!("\tep{}: Client IN err => STALL", endpoint);
1359
1360                            // Respond with STALL to any following IN/OUT transactions
1361                            usbc_regs().ueconset[endpoint].write(EndpointControl::STALLRQ::SET);
1362
1363                            // XXX: interrupts?
1364
1365                            // Remain in Init state?
1366                        }
1367                    }
1368                }
1369            }
1370            BulkInState::Delay => {
1371                // Endpoint interrupts should be handled already or disabled
1372                internal_err!("Not reached");
1373            }
1374        }
1375    }
1376
1377    #[allow(dead_code)]
1378    fn debug_show_d0(&self) {
1379        for bi in 0..1 {
1380            let b = &self.descriptors[0][bi];
1381            let addr = b.addr.get();
1382            let _buf = if addr.is_null() {
1383                None
1384            } else {
1385                unsafe {
1386                    Some(slice::from_raw_parts(
1387                        addr,
1388                        b.packet_size.read(PacketSize::BYTE_COUNT) as usize,
1389                    ))
1390                }
1391            };
1392
1393            debug1!(
1394                "B_0_{} \
1395                 \n     {:?}\
1396                 \n     {:?}\
1397                 \n     {:?}",
1398                bi, // core::ptr::addr_of!(b.addr), b.addr.get(),
1399                b.packet_size.get(),
1400                b.control_status.get(),
1401                _buf.map(HexBuf)
1402            );
1403        }
1404    }
1405
1406    pub fn mode(&self) -> Option<Mode> {
1407        match self.get_state() {
1408            State::Idle(mode) => Some(mode),
1409            State::Active(mode) => Some(mode),
1410            _ => None,
1411        }
1412    }
1413
1414    pub fn speed(&self) -> Option<Speed> {
1415        match self.mode() {
1416            Some(mode) => {
1417                match mode {
1418                    Mode::Device { speed, .. } => Some(speed),
1419                    Mode::Host => {
1420                        None // XX USBSTA.SPEED
1421                    }
1422                }
1423            }
1424            _ => None,
1425        }
1426    }
1427
1428    // TODO: Remote wakeup (Device -> Host, after receiving DEVICE_REMOTE_WAKEUP)
1429}
1430
1431#[inline]
1432fn endpoint_disable_interrupts(endpoint: usize, mask: FieldValue<u32, EndpointControl::Register>) {
1433    usbc_regs().ueconclr[endpoint].write(mask);
1434}
1435
1436#[inline]
1437fn endpoint_enable_interrupts(endpoint: usize, mask: FieldValue<u32, EndpointControl::Register>) {
1438    usbc_regs().ueconset[endpoint].write(mask);
1439}
1440
1441impl<'a> hil::usb::UsbController<'a> for Usbc<'a> {
1442    fn set_client(&self, client: &'a dyn hil::usb::Client<'a>) {
1443        self.client.set(client);
1444    }
1445
1446    fn endpoint_set_ctrl_buffer(&self, buf: &'a [VolatileCell<u8>]) {
1447        if buf.len() < 8 {
1448            client_err!("Bad endpoint buffer size");
1449        }
1450
1451        self.endpoint_bank_set_buffer(EndpointIndex::new(0), BankIndex::Bank0, buf);
1452    }
1453
1454    fn endpoint_set_in_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]) {
1455        if buf.len() < 8 {
1456            client_err!("Bad endpoint buffer size");
1457        }
1458
1459        self.endpoint_bank_set_buffer(EndpointIndex::new(endpoint), BankIndex::Bank0, buf);
1460    }
1461
1462    fn endpoint_set_out_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]) {
1463        if buf.len() < 8 {
1464            client_err!("Bad endpoint buffer size");
1465        }
1466
1467        // XXX: when implementing in_out endpoints, this should probably set a different slice than endpoint_set_in_buffer.
1468        self.endpoint_bank_set_buffer(EndpointIndex::new(endpoint), BankIndex::Bank0, buf);
1469    }
1470
1471    fn enable_as_device(&self, speed: hil::usb::DeviceSpeed) {
1472        let speed = match speed {
1473            hil::usb::DeviceSpeed::Full => Speed::Full,
1474            hil::usb::DeviceSpeed::Low => Speed::Low,
1475        };
1476
1477        match self.get_state() {
1478            State::Reset => self.enable(Mode::Device {
1479                speed,
1480                config: DeviceConfig::default(),
1481                state: DeviceState::default(),
1482            }),
1483            _ => client_err!("Already enabled"),
1484        }
1485    }
1486
1487    fn attach(&self) {
1488        match self.get_state() {
1489            State::Reset => client_warn!("Not enabled"),
1490            State::Active(_) => client_warn!("Already attached"),
1491            State::Idle(_) => self.attach(),
1492        }
1493    }
1494
1495    fn detach(&self) {
1496        match self.get_state() {
1497            State::Reset => client_warn!("Not enabled"),
1498            State::Idle(_) => client_warn!("Not attached"),
1499            State::Active(_) => self.detach(),
1500        }
1501    }
1502
1503    fn set_address(&self, addr: u16) {
1504        usbc_regs()
1505            .udcon
1506            .modify(DeviceControl::UADD.val(addr as u32));
1507
1508        debug1!("Set Address = {}", addr);
1509    }
1510
1511    fn enable_address(&self) {
1512        usbc_regs().udcon.modify(DeviceControl::ADDEN::SET);
1513
1514        debug1!(
1515            "Enable Address = {}",
1516            usbc_regs().udcon.read(DeviceControl::UADD)
1517        );
1518    }
1519
1520    fn endpoint_in_enable(&self, transfer_type: TransferType, endpoint: usize) {
1521        let endpoint_cfg = match transfer_type {
1522            TransferType::Control => {
1523                panic!("There is no IN control endpoint");
1524            }
1525            TransferType::Bulk => LocalRegisterCopy::new(From::from(
1526                EndpointConfig::EPTYPE::Bulk
1527                    + EndpointConfig::EPDIR::In
1528                    + EndpointConfig::EPSIZE::Bytes8
1529                    + EndpointConfig::EPBK::Single,
1530            )),
1531            TransferType::Interrupt | TransferType::Isochronous => unimplemented!(),
1532        };
1533
1534        self.endpoint_enable(endpoint, endpoint_cfg)
1535    }
1536
1537    fn endpoint_out_enable(&self, transfer_type: TransferType, endpoint: usize) {
1538        let endpoint_cfg = match transfer_type {
1539            TransferType::Control => LocalRegisterCopy::new(From::from(
1540                EndpointConfig::EPTYPE::Control
1541                    + EndpointConfig::EPDIR::Out
1542                    + EndpointConfig::EPSIZE::Bytes8
1543                    + EndpointConfig::EPBK::Single,
1544            )),
1545            TransferType::Bulk => LocalRegisterCopy::new(From::from(
1546                EndpointConfig::EPTYPE::Bulk
1547                    + EndpointConfig::EPDIR::Out
1548                    + EndpointConfig::EPSIZE::Bytes8
1549                    + EndpointConfig::EPBK::Single,
1550            )),
1551            TransferType::Interrupt | TransferType::Isochronous => unimplemented!(),
1552        };
1553
1554        self.endpoint_enable(endpoint, endpoint_cfg)
1555    }
1556
1557    fn endpoint_in_out_enable(&self, _transfer_type: TransferType, _endpoint: usize) {
1558        unimplemented!()
1559    }
1560
1561    fn endpoint_resume_in(&self, endpoint: usize) {
1562        let mut requests = self.requests[endpoint].get();
1563        requests.resume_in = true;
1564        self.requests[endpoint].set(requests);
1565
1566        // Immediately handle the request to resume the endpoint.
1567        self.handle_requests();
1568    }
1569
1570    fn endpoint_resume_out(&self, endpoint: usize) {
1571        let mut requests = self.requests[endpoint].get();
1572        requests.resume_out = true;
1573        self.requests[endpoint].set(requests);
1574
1575        // Immediately handle the request to resume the endpoint.
1576        self.handle_requests();
1577    }
1578}