From bb7a0ef8015ebb1901680ef698319c3a2c35bd60 Mon Sep 17 00:00:00 2001
From: Guillaume Endignoux <guillaumee@google.com>
Date: Wed, 11 Mar 2020 17:04:05 +0100
Subject: [PATCH] Sync patches with upstream Tock.

---
 patches/tock/01-persistent-storage.patch  |   4 +-
 patches/tock/02-usb.patch                 | 181 +-----
 patches/tock/04-increase-rom-nordic.patch |  24 -
 patches/tock/05-usb-cancel.patch          | 747 ----------------------
 third_party/tock                          |   2 +-
 5 files changed, 26 insertions(+), 932 deletions(-)
 delete mode 100644 patches/tock/04-increase-rom-nordic.patch
 delete mode 100644 patches/tock/05-usb-cancel.patch

diff --git a/patches/tock/01-persistent-storage.patch b/patches/tock/01-persistent-storage.patch
index ecfb0b0..57880c6 100644
--- a/patches/tock/01-persistent-storage.patch
+++ b/patches/tock/01-persistent-storage.patch
@@ -286,10 +286,10 @@ index 5abd2d84..5a726fdb 100644
 +    }
 +}
 diff --git a/kernel/src/callback.rs b/kernel/src/callback.rs
-index ece4a443..9a1afc84 100644
+index c812e0bf..bd1613b3 100644
 --- a/kernel/src/callback.rs
 +++ b/kernel/src/callback.rs
-@@ -52,6 +52,31 @@ impl AppId {
+@@ -130,6 +130,31 @@ impl AppId {
              (start, end)
          })
      }
diff --git a/patches/tock/02-usb.patch b/patches/tock/02-usb.patch
index a75a5b3..55f807b 100644
--- a/patches/tock/02-usb.patch
+++ b/patches/tock/02-usb.patch
@@ -124,11 +124,11 @@ index 105f7120..535e5cd8 100644
          ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
          nvmc: nvmc,
 diff --git a/capsules/src/driver.rs b/capsules/src/driver.rs
-index 9305e6a7..40466f44 100644
+index bfc06429..5858d352 100644
 --- a/capsules/src/driver.rs
 +++ b/capsules/src/driver.rs
-@@ -24,6 +24,7 @@ pub enum NUM {
-     Spi                   = 0x20001,
+@@ -25,6 +25,7 @@ pub enum NUM {
+     I2cMaster             = 0x20003,
      UsbUser               = 0x20005,
      I2cMasterSlave        = 0x20006,
 +    UsbCtap               = 0x20009,
@@ -509,10 +509,10 @@ index 00000000..da3d16d8
 +}
 diff --git a/capsules/src/usb/usbc_ctap_hid.rs b/capsules/src/usb/usbc_ctap_hid.rs
 new file mode 100644
-index 00000000..fdf7263a
+index 00000000..4b1916cf
 --- /dev/null
 +++ b/capsules/src/usb/usbc_ctap_hid.rs
-@@ -0,0 +1,352 @@
+@@ -0,0 +1,359 @@
 +//! A USB HID client of the USB hardware interface
 +
 +use super::descriptors::Buffer64;
@@ -603,8 +603,9 @@ index 00000000..fdf7263a
 +pub struct ClientCtapHID<'a, 'b, C: 'a> {
 +    client_ctrl: ClientCtrl<'a, 'static, C>,
 +
-+    // A 64-byte buffer for the endpoint
-+    buffer: Buffer64,
++    // 64-byte buffers for the endpoint
++    in_buffer: Buffer64,
++    out_buffer: Buffer64,
 +
 +    // Interaction with the client
 +    client: OptionalCell<&'b dyn CtapUsbClient>,
@@ -648,7 +649,8 @@ index 00000000..fdf7263a
 +                LANGUAGES,
 +                STRINGS,
 +            ),
-+            buffer: Default::default(),
++            in_buffer: Default::default(),
++            out_buffer: Default::default(),
 +            client: OptionalCell::empty(),
 +            tx_packet: OptionalCell::empty(),
 +            pending_in: Cell::new(false),
@@ -702,7 +704,7 @@ index 00000000..fdf7263a
 +    fn send_packet_to_client(&'a self) -> bool {
 +        // Copy the packet into a buffer to send to the client.
 +        let mut buf: [u8; 64] = [0; 64];
-+        for (i, x) in self.buffer.buf.iter().enumerate() {
++        for (i, x) in self.out_buffer.buf.iter().enumerate() {
 +            buf[i] = x.get();
 +        }
 +
@@ -735,11 +737,7 @@ index 00000000..fdf7263a
 +
 +    fn cancel_in_transaction(&'a self) -> bool {
 +        self.tx_packet.take();
-+        let result = self.pending_in.take();
-+        if result {
-+            self.controller().endpoint_cancel_in(1);
-+        }
-+        result
++        self.pending_in.take()
 +    }
 +
 +    fn cancel_out_transaction(&'a self) -> bool {
@@ -758,7 +756,10 @@ index 00000000..fdf7263a
 +        self.client_ctrl.enable();
 +
 +        // Set up the interrupt in-out endpoint
-+        self.controller().endpoint_set_buffer(1, &self.buffer.buf);
++        self.controller()
++            .endpoint_set_in_buffer(1, &self.in_buffer.buf);
++        self.controller()
++            .endpoint_set_out_buffer(1, &self.out_buffer.buf);
 +        self.controller()
 +            .endpoint_in_out_enable(TransferType::Interrupt, 1);
 +    }
@@ -808,7 +809,7 @@ index 00000000..fdf7263a
 +                }
 +
 +                if let Some(packet) = self.tx_packet.take() {
-+                    let buf = &self.buffer.buf;
++                    let buf = &self.in_buffer.buf;
 +                    for i in 0..64 {
 +                        buf[i].set(packet[i]);
 +                    }
@@ -861,149 +862,13 @@ index 00000000..fdf7263a
 +            panic!("Unexpected tx_packet while a packet was being transmitted.");
 +        }
 +        self.pending_in.set(false);
++
++        // Clear any pending packet on the receiving side.
++        // It's up to the client to handle the transmitted packet and decide if they want to
++        // receive another packet.
++        self.cancel_out_transaction();
++
 +        // Notify the client
 +        self.client.map(|client| client.packet_transmitted());
 +    }
 +}
-diff --git a/chips/nrf52/src/usbd.rs b/chips/nrf52/src/usbd.rs
-index 8ddb5895..8c1992cc 100644
---- a/chips/nrf52/src/usbd.rs
-+++ b/chips/nrf52/src/usbd.rs
-@@ -1499,7 +1499,23 @@ impl<'a> Usbd<'a> {
-             if epdatastatus.is_set(status_epin(endpoint)) {
-                 let (transfer_type, direction, state) =
-                     self.descriptors[endpoint].state.get().bulk_state();
--                assert_eq!(state, BulkState::InData);
-+                match state {
-+                    BulkState::InData => {
-+                        // Totally expected state. Nothing to do.
-+                    }
-+                    BulkState::Init => {
-+                        internal_warn!(
-+                            "Received a stale epdata IN in an unexpected state: {:?}",
-+                            state
-+                        );
-+                    }
-+                    BulkState::OutDelay
-+                    | BulkState::OutData
-+                    | BulkState::OutDma
-+                    | BulkState::InDma => {
-+                        internal_err!("Unexpected state: {:?}", state);
-+                    }
-+                }
-                 self.descriptors[endpoint].state.set(EndpointState::Bulk(
-                     transfer_type,
-                     direction,
-@@ -1677,7 +1693,7 @@ impl<'a> Usbd<'a> {
-     }
- 
-     fn transmit_in(&self, endpoint: usize) {
--        debug_info!("transmit_in({})", endpoint);
-+        debug_events!("transmit_in({})", endpoint);
-         let regs = &*self.registers;
- 
-         self.client.map(|client| {
-@@ -1717,7 +1733,7 @@ impl<'a> Usbd<'a> {
-     }
- 
-     fn transmit_out(&self, endpoint: usize) {
--        debug_info!("transmit_out({})", endpoint);
-+        debug_events!("transmit_out({})", endpoint);
- 
-         let (transfer_type, direction, state) = self.descriptors[endpoint].state.get().bulk_state();
-         // Starting the DMA can only happen in the OutData state, i.e. after an EPDATA event.
-@@ -1882,11 +1898,13 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> {
-     }
- 
-     fn endpoint_resume_in(&self, endpoint: usize) {
-+        debug_events!("endpoint_resume_in({})", endpoint);
-+
-         let (_, direction, _) = self.descriptors[endpoint].state.get().bulk_state();
-         assert!(direction.has_in());
- 
-         if self.dma_pending.get() {
--            debug_info!("requesting resume_in[{}]", endpoint);
-+            debug_events!("requesting resume_in[{}]", endpoint);
-             // A DMA is already pending. Schedule the resume for later.
-             self.descriptors[endpoint].request_transmit_in.set(true);
-         } else {
-@@ -1896,6 +1914,8 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> {
-     }
- 
-     fn endpoint_resume_out(&self, endpoint: usize) {
-+        debug_events!("endpoint_resume_out({})", endpoint);
-+
-         let (transfer_type, direction, state) = self.descriptors[endpoint].state.get().bulk_state();
-         assert!(direction.has_out());
- 
-@@ -1914,7 +1934,7 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> {
-                 // happened in the meantime. This pending transaction will now
-                 // continue in transmit_out().
-                 if self.dma_pending.get() {
--                    debug_info!("requesting resume_out[{}]", endpoint);
-+                    debug_events!("requesting resume_out[{}]", endpoint);
-                     // A DMA is already pending. Schedule the resume for later.
-                     self.descriptors[endpoint].request_transmit_out.set(true);
-                 } else {
-@@ -1927,6 +1947,20 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> {
-             }
-         }
-     }
-+
-+    fn endpoint_cancel_in(&self, endpoint: usize) {
-+        debug_events!("endpoint_cancel_in({})", endpoint);
-+
-+        let (transfer_type, direction, state) = self.descriptors[endpoint].state.get().bulk_state();
-+        assert!(direction.has_in());
-+        assert_eq!(state, BulkState::InData);
-+
-+        self.descriptors[endpoint].state.set(EndpointState::Bulk(
-+            transfer_type,
-+            direction,
-+            BulkState::Init,
-+        ));
-+    }
- }
- 
- fn status_epin(ep: usize) -> Field<u32, EndpointStatus::Register> {
-diff --git a/chips/nrf52840/src/lib.rs b/chips/nrf52840/src/lib.rs
-index 9d58a705..942d0288 100644
---- a/chips/nrf52840/src/lib.rs
-+++ b/chips/nrf52840/src/lib.rs
-@@ -2,7 +2,7 @@
- 
- pub use nrf52::{
-     acomp, adc, aes, ble_radio, clock, constants, crt1, ficr, i2c, ieee802154_radio, init, nvmc,
--    pinmux, ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr,
-+    pinmux, ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr, usbd,
- };
- pub mod chip;
- pub mod gpio;
-diff --git a/chips/sam4l/src/usbc/mod.rs b/chips/sam4l/src/usbc/mod.rs
-index 35f3bb7c..28a0b9f9 100644
---- a/chips/sam4l/src/usbc/mod.rs
-+++ b/chips/sam4l/src/usbc/mod.rs
-@@ -1547,6 +1547,10 @@ impl hil::usb::UsbController<'a> for Usbc<'a> {
-         requests.resume_out = true;
-         self.requests[endpoint].set(requests);
-     }
-+
-+    fn endpoint_cancel_in(&self, _endpoint: usize) {
-+        unimplemented!()
-+    }
- }
- 
- /// Static state to manage the USBC
-diff --git a/kernel/src/hil/usb.rs b/kernel/src/hil/usb.rs
-index 846f5e93..64610fa5 100644
---- a/kernel/src/hil/usb.rs
-+++ b/kernel/src/hil/usb.rs
-@@ -27,6 +27,8 @@ pub trait UsbController<'a> {
-     fn endpoint_resume_in(&self, endpoint: usize);
- 
-     fn endpoint_resume_out(&self, endpoint: usize);
-+
-+    fn endpoint_cancel_in(&self, endpoint: usize);
- }
- 
- #[derive(Clone, Copy, Debug)]
diff --git a/patches/tock/04-increase-rom-nordic.patch b/patches/tock/04-increase-rom-nordic.patch
deleted file mode 100644
index 83948f8..0000000
--- a/patches/tock/04-increase-rom-nordic.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff --git a/boards/nordic/nrf52840_dongle/layout.ld b/boards/nordic/nrf52840_dongle/layout.ld
-index 657b0d26..f86b2321 100644
---- a/boards/nordic/nrf52840_dongle/layout.ld
-+++ b/boards/nordic/nrf52840_dongle/layout.ld
-@@ -1,6 +1,6 @@
- MEMORY
- {
--  rom (rx)  : ORIGIN = 0x00000000, LENGTH = 128K
-+  rom (rx)  : ORIGIN = 0x00000000, LENGTH = 192K
-   prog (rx) : ORIGIN = 0x00030000, LENGTH = 832K
-   ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
- }
-diff --git a/boards/nordic/nrf52840dk/layout.ld b/boards/nordic/nrf52840dk/layout.ld
-index 657b0d26..f86b2321 100644
---- a/boards/nordic/nrf52840dk/layout.ld
-+++ b/boards/nordic/nrf52840dk/layout.ld
-@@ -1,6 +1,6 @@
- MEMORY
- {
--  rom (rx)  : ORIGIN = 0x00000000, LENGTH = 128K
-+  rom (rx)  : ORIGIN = 0x00000000, LENGTH = 192K
-   prog (rx) : ORIGIN = 0x00030000, LENGTH = 832K
-   ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
- }
diff --git a/patches/tock/05-usb-cancel.patch b/patches/tock/05-usb-cancel.patch
deleted file mode 100644
index f853971..0000000
--- a/patches/tock/05-usb-cancel.patch
+++ /dev/null
@@ -1,747 +0,0 @@
-diff --git a/capsules/src/usb/usbc_client.rs b/capsules/src/usb/usbc_client.rs
-index b0678c23..9fb43781 100644
---- a/capsules/src/usb/usbc_client.rs
-+++ b/capsules/src/usb/usbc_client.rs
-@@ -115,11 +115,11 @@ impl<'a, C: hil::usb::UsbController<'a>> hil::usb::Client<'a> for Client<'a, C>
-         self.client_ctrl.enable();
- 
-         // Set up a bulk-in endpoint for debugging
--        self.controller().endpoint_set_buffer(1, self.buffer(1));
-+        self.controller().endpoint_set_in_buffer(1, self.buffer(1));
-         self.controller().endpoint_in_enable(TransferType::Bulk, 1);
- 
-         // Set up a bulk-out endpoint for debugging
--        self.controller().endpoint_set_buffer(2, self.buffer(2));
-+        self.controller().endpoint_set_out_buffer(2, self.buffer(2));
-         self.controller().endpoint_out_enable(TransferType::Bulk, 2);
-     }
- 
-diff --git a/capsules/src/usb/usbc_client_ctrl.rs b/capsules/src/usb/usbc_client_ctrl.rs
-index 2aaca0cc..5f9b253c 100644
---- a/capsules/src/usb/usbc_client_ctrl.rs
-+++ b/capsules/src/usb/usbc_client_ctrl.rs
-@@ -201,7 +201,7 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> ClientCtrl<'a, 'b, C> {
-     pub fn enable(&'a self) {
-         // Set up the default control endpoint
-         self.controller
--            .endpoint_set_buffer(0, &self.ctrl_buffer.buf);
-+            .endpoint_set_ctrl_buffer(&self.ctrl_buffer.buf);
-         self.controller
-             .enable_as_device(hil::usb::DeviceSpeed::Full); // must be Full for Bulk transfers
-         self.controller
-diff --git a/capsules/src/usb/usbc_ctap_hid.rs b/capsules/src/usb/usbc_ctap_hid.rs
-index fdf7263a..4b1916cf 100644
---- a/capsules/src/usb/usbc_ctap_hid.rs
-+++ b/capsules/src/usb/usbc_ctap_hid.rs
-@@ -88,8 +88,9 @@ static HID: HIDDescriptor<'static> = HIDDescriptor {
- pub struct ClientCtapHID<'a, 'b, C: 'a> {
-     client_ctrl: ClientCtrl<'a, 'static, C>,
- 
--    // A 64-byte buffer for the endpoint
--    buffer: Buffer64,
-+    // 64-byte buffers for the endpoint
-+    in_buffer: Buffer64,
-+    out_buffer: Buffer64,
- 
-     // Interaction with the client
-     client: OptionalCell<&'b dyn CtapUsbClient>,
-@@ -133,7 +134,8 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> ClientCtapHID<'a, 'b, C> {
-                 LANGUAGES,
-                 STRINGS,
-             ),
--            buffer: Default::default(),
-+            in_buffer: Default::default(),
-+            out_buffer: Default::default(),
-             client: OptionalCell::empty(),
-             tx_packet: OptionalCell::empty(),
-             pending_in: Cell::new(false),
-@@ -187,7 +189,7 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> ClientCtapHID<'a, 'b, C> {
-     fn send_packet_to_client(&'a self) -> bool {
-         // Copy the packet into a buffer to send to the client.
-         let mut buf: [u8; 64] = [0; 64];
--        for (i, x) in self.buffer.buf.iter().enumerate() {
-+        for (i, x) in self.out_buffer.buf.iter().enumerate() {
-             buf[i] = x.get();
-         }
- 
-@@ -220,11 +222,7 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> ClientCtapHID<'a, 'b, C> {
- 
-     fn cancel_in_transaction(&'a self) -> bool {
-         self.tx_packet.take();
--        let result = self.pending_in.take();
--        if result {
--            self.controller().endpoint_cancel_in(1);
--        }
--        result
-+        self.pending_in.take()
-     }
- 
-     fn cancel_out_transaction(&'a self) -> bool {
-@@ -243,7 +241,10 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> hil::usb::Client<'a> for ClientCtap
-         self.client_ctrl.enable();
- 
-         // Set up the interrupt in-out endpoint
--        self.controller().endpoint_set_buffer(1, &self.buffer.buf);
-+        self.controller()
-+            .endpoint_set_in_buffer(1, &self.in_buffer.buf);
-+        self.controller()
-+            .endpoint_set_out_buffer(1, &self.out_buffer.buf);
-         self.controller()
-             .endpoint_in_out_enable(TransferType::Interrupt, 1);
-     }
-@@ -293,7 +294,7 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> hil::usb::Client<'a> for ClientCtap
-                 }
- 
-                 if let Some(packet) = self.tx_packet.take() {
--                    let buf = &self.buffer.buf;
-+                    let buf = &self.in_buffer.buf;
-                     for i in 0..64 {
-                         buf[i].set(packet[i]);
-                     }
-@@ -346,6 +347,12 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> hil::usb::Client<'a> for ClientCtap
-             panic!("Unexpected tx_packet while a packet was being transmitted.");
-         }
-         self.pending_in.set(false);
-+
-+        // Clear any pending packet on the receiving side.
-+        // It's up to the client to handle the transmitted packet and decide if they want to
-+        // receive another packet.
-+        self.cancel_out_transaction();
-+
-         // Notify the client
-         self.client.map(|client| client.packet_transmitted());
-     }
-diff --git a/chips/nrf52/src/usbd.rs b/chips/nrf52/src/usbd.rs
-index 8c1992cc..972871d0 100644
---- a/chips/nrf52/src/usbd.rs
-+++ b/chips/nrf52/src/usbd.rs
-@@ -623,7 +623,7 @@ pub enum UsbState {
- pub enum EndpointState {
-     Disabled,
-     Ctrl(CtrlState),
--    Bulk(TransferType, EndpointDirection, BulkState),
-+    Bulk(TransferType, Option<BulkInState>, Option<BulkOutState>),
- }
- 
- impl EndpointState {
-@@ -634,10 +634,10 @@ impl EndpointState {
-         }
-     }
- 
--    fn bulk_state(self) -> (TransferType, EndpointDirection, BulkState) {
-+    fn bulk_state(self) -> (TransferType, Option<BulkInState>, Option<BulkOutState>) {
-         match self {
--            EndpointState::Bulk(transfer_type, direction, state) => {
--                (transfer_type, direction, state)
-+            EndpointState::Bulk(transfer_type, in_state, out_state) => {
-+                (transfer_type, in_state, out_state)
-             }
-             _ => panic!("Expected EndpointState::Bulk"),
-         }
-@@ -651,31 +651,18 @@ pub enum CtrlState {
-     ReadStatus,
- }
- 
--#[derive(Copy, Clone, Debug)]
--pub enum EndpointDirection {
--    In,
--    Out,
--    InOut,
--}
--
--impl EndpointDirection {
--    fn has_in(&self) -> bool {
--        match self {
--            EndpointDirection::In | EndpointDirection::InOut => true,
--            EndpointDirection::Out => false,
--        }
--    }
--
--    fn has_out(&self) -> bool {
--        match self {
--            EndpointDirection::Out | EndpointDirection::InOut => true,
--            EndpointDirection::In => false,
--        }
--    }
-+#[derive(Copy, Clone, PartialEq, Debug)]
-+pub enum BulkInState {
-+    // The endpoint is ready to perform transactions.
-+    Init,
-+    // There is a pending DMA transfer on this IN endpoint.
-+    InDma,
-+    // There is a pending IN packet transfer on this endpoint.
-+    InData,
- }
- 
- #[derive(Copy, Clone, PartialEq, Debug)]
--pub enum BulkState {
-+pub enum BulkOutState {
-     // The endpoint is ready to perform transactions.
-     Init,
-     // There is a pending OUT packet in this endpoint's buffer, to be read by
-@@ -685,14 +672,11 @@ pub enum BulkState {
-     OutData,
-     // There is a pending DMA transfer on this OUT endpoint.
-     OutDma,
--    // There is a pending DMA transfer on this IN endpoint.
--    InDma,
--    // There is a pending IN packet transfer on this endpoint.
--    InData,
- }
- 
- pub struct Endpoint<'a> {
--    slice: OptionalCell<&'a [VolatileCell<u8>]>,
-+    slice_in: OptionalCell<&'a [VolatileCell<u8>]>,
-+    slice_out: OptionalCell<&'a [VolatileCell<u8>]>,
-     state: Cell<EndpointState>,
-     // The USB controller can only process one DMA transfer at a time (over all endpoints). The
-     // request_transmit_* bits allow to queue transfers until the DMA becomes available again.
-@@ -705,7 +689,8 @@ pub struct Endpoint<'a> {
- impl Endpoint<'_> {
-     const fn new() -> Self {
-         Endpoint {
--            slice: OptionalCell::empty(),
-+            slice_in: OptionalCell::empty(),
-+            slice_out: OptionalCell::empty(),
-             state: Cell::new(EndpointState::Disabled),
-             request_transmit_in: Cell::new(false),
-             request_transmit_out: Cell::new(false),
-@@ -914,18 +899,12 @@ impl<'a> Usbd<'a> {
-                     chip_revision.get()
-                 );
-             }
--            Some(ChipRevision::REV::Value::REVC) => {
-+            Some(ChipRevision::REV::Value::REVC) | Some(ChipRevision::REV::Value::REVD) => {
-                 debug_info!(
-                     "Your chip is NRF52840 revision {}. The USB stack was tested on your chip :)",
-                     chip_revision.get()
-                 );
-             }
--            Some(ChipRevision::REV::Value::REVD) => {
--                internal_warn!(
--                    "Your chip is NRF52840 revision {}. Although this USB implementation should be compatible, your chip hasn't been tested.",
--                    chip_revision.get()
--                );
--            }
-             None => {
-                 internal_warn!(
-                     "Your chip is NRF52840 revision {} (unknown revision). Although this USB implementation should be compatible, your chip hasn't been tested.",
-@@ -1026,7 +1005,7 @@ impl<'a> Usbd<'a> {
-         });
-         self.descriptors[endpoint].state.set(match endpoint {
-             0 => EndpointState::Ctrl(CtrlState::Init),
--            1..=7 => EndpointState::Bulk(transfer_type, EndpointDirection::In, BulkState::Init),
-+            1..=7 => EndpointState::Bulk(transfer_type, Some(BulkInState::Init), None),
-             8 => unimplemented!("isochronous endpoint"),
-             _ => unreachable!("unexisting endpoint"),
-         });
-@@ -1064,7 +1043,7 @@ impl<'a> Usbd<'a> {
-         });
-         self.descriptors[endpoint].state.set(match endpoint {
-             0 => EndpointState::Ctrl(CtrlState::Init),
--            1..=7 => EndpointState::Bulk(transfer_type, EndpointDirection::Out, BulkState::Init),
-+            1..=7 => EndpointState::Bulk(transfer_type, None, Some(BulkOutState::Init)),
-             8 => unimplemented!("isochronous endpoint"),
-             _ => unreachable!("unexisting endpoint"),
-         });
-@@ -1114,7 +1093,11 @@ impl<'a> Usbd<'a> {
-         });
-         self.descriptors[endpoint].state.set(match endpoint {
-             0 => EndpointState::Ctrl(CtrlState::Init),
--            1..=7 => EndpointState::Bulk(transfer_type, EndpointDirection::InOut, BulkState::Init),
-+            1..=7 => EndpointState::Bulk(
-+                transfer_type,
-+                Some(BulkInState::Init),
-+                Some(BulkOutState::Init),
-+            ),
-             8 => unimplemented!("isochronous endpoint"),
-             _ => unreachable!("unexisting endpoint"),
-         });
-@@ -1304,13 +1287,13 @@ impl<'a> Usbd<'a> {
-             match desc.state.get() {
-                 EndpointState::Disabled => {}
-                 EndpointState::Ctrl(_) => desc.state.set(EndpointState::Ctrl(CtrlState::Init)),
--                EndpointState::Bulk(transfer_type, direction, _) => {
-+                EndpointState::Bulk(transfer_type, in_state, out_state) => {
-                     desc.state.set(EndpointState::Bulk(
-                         transfer_type,
--                        direction,
--                        BulkState::Init,
-+                        in_state.map(|_| BulkInState::Init),
-+                        out_state.map(|_| BulkOutState::Init),
-                     ));
--                    if direction.has_out() {
-+                    if out_state.is_some() {
-                         // Accept incoming OUT packets.
-                         regs.size_epout[ep].set(0);
-                     }
-@@ -1347,13 +1330,13 @@ impl<'a> Usbd<'a> {
-         match endpoint {
-             0 => {}
-             1..=7 => {
--                let (transfer_type, direction, state) =
-+                let (transfer_type, in_state, out_state) =
-                     self.descriptors[endpoint].state.get().bulk_state();
--                assert_eq!(state, BulkState::InDma);
-+                assert_eq!(in_state, Some(BulkInState::InDma));
-                 self.descriptors[endpoint].state.set(EndpointState::Bulk(
-                     transfer_type,
--                    direction,
--                    BulkState::InData,
-+                    Some(BulkInState::InData),
-+                    out_state,
-                 ));
-             }
-             8 => unimplemented!("isochronous endpoint"),
-@@ -1405,25 +1388,25 @@ impl<'a> Usbd<'a> {
-             1..=7 => {
-                 // Notify the client about the new packet.
-                 let packet_bytes = regs.size_epout[endpoint].get();
--                let (transfer_type, direction, state) =
-+                let (transfer_type, in_state, out_state) =
-                     self.descriptors[endpoint].state.get().bulk_state();
--                assert_eq!(state, BulkState::OutDma);
-+                assert_eq!(out_state, Some(BulkOutState::OutDma));
- 
--                self.debug_packet("out", packet_bytes as usize, endpoint);
-+                self.debug_out_packet(packet_bytes as usize, endpoint);
- 
-                 self.client.map(|client| {
-                     let result = client.packet_out(transfer_type, endpoint, packet_bytes);
-                     debug_packets!("packet_out => {:?}", result);
--                    let newstate = match result {
-+                    let new_out_state = match result {
-                         hil::usb::OutResult::Ok => {
-                             // Indicate that the endpoint is ready to receive data again.
-                             regs.size_epout[endpoint].set(0);
--                            BulkState::Init
-+                            BulkOutState::Init
-                         }
- 
-                         hil::usb::OutResult::Delay => {
-                             // We can't send the packet now. Wait for a resume_out call from the client.
--                            BulkState::OutDelay
-+                            BulkOutState::OutDelay
-                         }
- 
-                         hil::usb::OutResult::Error => {
-@@ -1432,13 +1415,13 @@ impl<'a> Usbd<'a> {
-                                     + EndpointStall::IO::Out
-                                     + EndpointStall::STALL::Stall,
-                             );
--                            BulkState::Init
-+                            BulkOutState::Init
-                         }
-                     };
-                     self.descriptors[endpoint].state.set(EndpointState::Bulk(
-                         transfer_type,
--                        direction,
--                        newstate,
-+                        in_state,
-+                        Some(new_out_state),
-                     ));
-                 });
-             }
-@@ -1497,29 +1480,27 @@ impl<'a> Usbd<'a> {
-         // Endpoint 8 (isochronous) doesn't receive any EPDATA event.
-         for endpoint in 1..NUM_ENDPOINTS {
-             if epdatastatus.is_set(status_epin(endpoint)) {
--                let (transfer_type, direction, state) =
-+                let (transfer_type, in_state, out_state) =
-                     self.descriptors[endpoint].state.get().bulk_state();
--                match state {
--                    BulkState::InData => {
-+                assert!(in_state.is_some());
-+                match in_state.unwrap() {
-+                    BulkInState::InData => {
-                         // Totally expected state. Nothing to do.
-                     }
--                    BulkState::Init => {
-+                    BulkInState::Init => {
-                         internal_warn!(
-                             "Received a stale epdata IN in an unexpected state: {:?}",
--                            state
-+                            in_state
-                         );
-                     }
--                    BulkState::OutDelay
--                    | BulkState::OutData
--                    | BulkState::OutDma
--                    | BulkState::InDma => {
--                        internal_err!("Unexpected state: {:?}", state);
-+                    BulkInState::InDma => {
-+                        internal_err!("Unexpected state: {:?}", in_state);
-                     }
-                 }
-                 self.descriptors[endpoint].state.set(EndpointState::Bulk(
-                     transfer_type,
--                    direction,
--                    BulkState::Init,
-+                    Some(BulkInState::Init),
-+                    out_state,
-                 ));
-                 self.client
-                     .map(|client| client.packet_transmitted(endpoint));
-@@ -1530,28 +1511,26 @@ impl<'a> Usbd<'a> {
-         // Endpoint 8 (isochronous) doesn't receive any EPDATA event.
-         for ep in 1..NUM_ENDPOINTS {
-             if epdatastatus.is_set(status_epout(ep)) {
--                let (transfer_type, direction, state) =
-+                let (transfer_type, in_state, out_state) =
-                     self.descriptors[ep].state.get().bulk_state();
--                match state {
--                    BulkState::Init => {
-+                assert!(out_state.is_some());
-+                match out_state.unwrap() {
-+                    BulkOutState::Init => {
-                         // The endpoint is ready to receive data. Request a transmit_out.
-                         self.descriptors[ep].request_transmit_out.set(true);
-                     }
--                    BulkState::OutDelay => {
-+                    BulkOutState::OutDelay => {
-                         // The endpoint will be resumed later by the client application with transmit_out().
-                     }
--                    BulkState::OutData
--                    | BulkState::OutDma
--                    | BulkState::InDma
--                    | BulkState::InData => {
--                        internal_err!("Unexpected state: {:?}", state);
-+                    BulkOutState::OutData | BulkOutState::OutDma => {
-+                        internal_err!("Unexpected state: {:?}", out_state);
-                     }
-                 }
-                 // Indicate that the endpoint now has data available.
-                 self.descriptors[ep].state.set(EndpointState::Bulk(
-                     transfer_type,
--                    direction,
--                    BulkState::OutData,
-+                    in_state,
-+                    Some(BulkOutState::OutData),
-                 ));
-             }
-         }
-@@ -1564,8 +1543,8 @@ impl<'a> Usbd<'a> {
-         let state = self.descriptors[endpoint].state.get().ctrl_state();
-         match state {
-             CtrlState::Init => {
--                let ep_buf = &self.descriptors[endpoint].slice;
--                let ep_buf = ep_buf.expect("No slice set for this descriptor");
-+                let ep_buf = &self.descriptors[endpoint].slice_out;
-+                let ep_buf = ep_buf.expect("No OUT slice set for this descriptor");
-                 if ep_buf.len() < 8 {
-                     panic!("EP0 DMA buffer length < 8");
-                 }
-@@ -1697,21 +1676,21 @@ impl<'a> Usbd<'a> {
-         let regs = &*self.registers;
- 
-         self.client.map(|client| {
--            let (transfer_type, direction, state) =
-+            let (transfer_type, in_state, out_state) =
-                 self.descriptors[endpoint].state.get().bulk_state();
--            assert_eq!(state, BulkState::Init);
-+            assert_eq!(in_state, Some(BulkInState::Init));
- 
-             let result = client.packet_in(transfer_type, endpoint);
-             debug_packets!("packet_in => {:?}", result);
--            let newstate = match result {
-+            let new_in_state = match result {
-                 hil::usb::InResult::Packet(size) => {
-                     self.start_dma_in(endpoint, size);
--                    BulkState::InDma
-+                    BulkInState::InDma
-                 }
- 
-                 hil::usb::InResult::Delay => {
-                     // No packet to send now. Wait for a resume call from the client.
--                    BulkState::Init
-+                    BulkInState::Init
-                 }
- 
-                 hil::usb::InResult::Error => {
-@@ -1720,14 +1699,14 @@ impl<'a> Usbd<'a> {
-                             + EndpointStall::IO::In
-                             + EndpointStall::STALL::Stall,
-                     );
--                    BulkState::Init
-+                    BulkInState::Init
-                 }
-             };
- 
-             self.descriptors[endpoint].state.set(EndpointState::Bulk(
-                 transfer_type,
--                direction,
--                newstate,
-+                Some(new_in_state),
-+                out_state,
-             ));
-         });
-     }
-@@ -1735,15 +1714,16 @@ impl<'a> Usbd<'a> {
-     fn transmit_out(&self, endpoint: usize) {
-         debug_events!("transmit_out({})", endpoint);
- 
--        let (transfer_type, direction, state) = self.descriptors[endpoint].state.get().bulk_state();
-+        let (transfer_type, in_state, out_state) =
-+            self.descriptors[endpoint].state.get().bulk_state();
-         // Starting the DMA can only happen in the OutData state, i.e. after an EPDATA event.
--        assert_eq!(state, BulkState::OutData);
-+        assert_eq!(out_state, Some(BulkOutState::OutData));
-         self.start_dma_out(endpoint);
- 
-         self.descriptors[endpoint].state.set(EndpointState::Bulk(
-             transfer_type,
--            direction,
--            BulkState::OutDma,
-+            in_state,
-+            Some(BulkOutState::OutDma),
-         ));
-     }
- 
-@@ -1751,9 +1731,9 @@ impl<'a> Usbd<'a> {
-         let regs = &*self.registers;
- 
-         let slice = self.descriptors[endpoint]
--            .slice
--            .expect("No slice set for this descriptor");
--        self.debug_packet("in", size, endpoint);
-+            .slice_in
-+            .expect("No IN slice set for this descriptor");
-+        self.debug_in_packet(size, endpoint);
- 
-         // Start DMA transfer
-         self.set_pending_dma();
-@@ -1766,8 +1746,8 @@ impl<'a> Usbd<'a> {
-         let regs = &*self.registers;
- 
-         let slice = self.descriptors[endpoint]
--            .slice
--            .expect("No slice set for this descriptor");
-+            .slice_out
-+            .expect("No OUT slice set for this descriptor");
- 
-         // Start DMA transfer
-         self.set_pending_dma();
-@@ -1777,10 +1757,27 @@ impl<'a> Usbd<'a> {
-     }
- 
-     // Debug-only function
--    fn debug_packet(&self, _title: &str, size: usize, endpoint: usize) {
-+    fn debug_in_packet(&self, size: usize, endpoint: usize) {
-+        let slice = self.descriptors[endpoint]
-+            .slice_in
-+            .expect("No IN slice set for this descriptor");
-+        if size > slice.len() {
-+            panic!("Packet is too large: {}", size);
-+        }
-+
-+        let mut packet_hex = [0; 128];
-+        packet_to_hex(slice, &mut packet_hex);
-+        debug_packets!(
-+            "in={}",
-+            core::str::from_utf8(&packet_hex[..(2 * size)]).unwrap()
-+        );
-+    }
-+
-+    // Debug-only function
-+    fn debug_out_packet(&self, size: usize, endpoint: usize) {
-         let slice = self.descriptors[endpoint]
--            .slice
--            .expect("No slice set for this descriptor");
-+            .slice_out
-+            .expect("No OUT slice set for this descriptor");
-         if size > slice.len() {
-             panic!("Packet is too large: {}", size);
-         }
-@@ -1788,8 +1785,7 @@ impl<'a> Usbd<'a> {
-         let mut packet_hex = [0; 128];
-         packet_to_hex(slice, &mut packet_hex);
-         debug_packets!(
--            "{}={}",
--            _title,
-+            "out={}",
-             core::str::from_utf8(&packet_hex[..(2 * size)]).unwrap()
-         );
-     }
-@@ -1807,17 +1803,41 @@ impl<'a> power::PowerClient for Usbd<'a> {
- }
- 
- impl<'a> hil::usb::UsbController<'a> for Usbd<'a> {
--    fn endpoint_set_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]) {
-+    fn endpoint_set_ctrl_buffer(&self, buf: &'a [VolatileCell<u8>]) {
-+        if buf.len() < 8 {
-+            panic!("Endpoint buffer must be at least 8 bytes");
-+        }
-+        if !buf.len().is_power_of_two() {
-+            panic!("Buffer size must be a power of 2");
-+        }
-+        self.descriptors[0].slice_in.set(buf);
-+        self.descriptors[0].slice_out.set(buf);
-+    }
-+
-+    fn endpoint_set_in_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]) {
-+        if buf.len() < 8 {
-+            panic!("Endpoint buffer must be at least 8 bytes");
-+        }
-+        if !buf.len().is_power_of_two() {
-+            panic!("Buffer size must be a power of 2");
-+        }
-+        if endpoint == 0 || endpoint >= NUM_ENDPOINTS {
-+            panic!("Endpoint number is invalid");
-+        }
-+        self.descriptors[endpoint].slice_in.set(buf);
-+    }
-+
-+    fn endpoint_set_out_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]) {
-         if buf.len() < 8 {
-             panic!("Endpoint buffer must be at least 8 bytes");
-         }
-         if !buf.len().is_power_of_two() {
-             panic!("Buffer size must be a power of 2");
-         }
--        if endpoint >= NUM_ENDPOINTS {
--            panic!("Endpoint number is too high");
-+        if endpoint == 0 || endpoint >= NUM_ENDPOINTS {
-+            panic!("Endpoint number is invalid");
-         }
--        self.descriptors[endpoint].slice.set(buf);
-+        self.descriptors[endpoint].slice_out.set(buf);
-     }
- 
-     fn enable_as_device(&self, speed: hil::usb::DeviceSpeed) {
-@@ -1900,8 +1920,8 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> {
-     fn endpoint_resume_in(&self, endpoint: usize) {
-         debug_events!("endpoint_resume_in({})", endpoint);
- 
--        let (_, direction, _) = self.descriptors[endpoint].state.get().bulk_state();
--        assert!(direction.has_in());
-+        let (_, in_state, _) = self.descriptors[endpoint].state.get().bulk_state();
-+        assert!(in_state.is_some());
- 
-         if self.dma_pending.get() {
-             debug_events!("requesting resume_in[{}]", endpoint);
-@@ -1916,20 +1936,21 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> {
-     fn endpoint_resume_out(&self, endpoint: usize) {
-         debug_events!("endpoint_resume_out({})", endpoint);
- 
--        let (transfer_type, direction, state) = self.descriptors[endpoint].state.get().bulk_state();
--        assert!(direction.has_out());
-+        let (transfer_type, in_state, out_state) =
-+            self.descriptors[endpoint].state.get().bulk_state();
-+        assert!(out_state.is_some());
- 
--        match state {
--            BulkState::OutDelay => {
-+        match out_state.unwrap() {
-+            BulkOutState::OutDelay => {
-                 // The endpoint has now finished processing the last ENDEPOUT. No EPDATA event
-                 // happened in the meantime, so the state is now back to Init.
-                 self.descriptors[endpoint].state.set(EndpointState::Bulk(
-                     transfer_type,
--                    direction,
--                    BulkState::Init,
-+                    in_state,
-+                    Some(BulkOutState::Init),
-                 ));
-             }
--            BulkState::OutData => {
-+            BulkOutState::OutData => {
-                 // Although the client reported a delay before, an EPDATA event has
-                 // happened in the meantime. This pending transaction will now
-                 // continue in transmit_out().
-@@ -1942,25 +1963,11 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> {
-                     self.transmit_out(endpoint);
-                 }
-             }
--            BulkState::Init | BulkState::OutDma | BulkState::InDma | BulkState::InData => {
--                internal_err!("Unexpected state: {:?}", state);
-+            BulkOutState::Init | BulkOutState::OutDma => {
-+                internal_err!("Unexpected state: {:?}", out_state);
-             }
-         }
-     }
--
--    fn endpoint_cancel_in(&self, endpoint: usize) {
--        debug_events!("endpoint_cancel_in({})", endpoint);
--
--        let (transfer_type, direction, state) = self.descriptors[endpoint].state.get().bulk_state();
--        assert!(direction.has_in());
--        assert_eq!(state, BulkState::InData);
--
--        self.descriptors[endpoint].state.set(EndpointState::Bulk(
--            transfer_type,
--            direction,
--            BulkState::Init,
--        ));
--    }
- }
- 
- fn status_epin(ep: usize) -> Field<u32, EndpointStatus::Register> {
-diff --git a/chips/sam4l/src/usbc/mod.rs b/chips/sam4l/src/usbc/mod.rs
-index 28a0b9f9..ab5b636f 100644
---- a/chips/sam4l/src/usbc/mod.rs
-+++ b/chips/sam4l/src/usbc/mod.rs
-@@ -1438,11 +1438,28 @@ fn endpoint_enable_interrupts(endpoint: usize, mask: FieldValue<u32, EndpointCon
- }
- 
- impl hil::usb::UsbController<'a> for Usbc<'a> {
--    fn endpoint_set_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]) {
-+    fn endpoint_set_ctrl_buffer(&self, buf: &'a [VolatileCell<u8>]) {
-         if buf.len() != 8 {
-             client_err!("Bad endpoint buffer size");
-         }
- 
-+        self._endpoint_bank_set_buffer(EndpointIndex::new(0), BankIndex::Bank0, buf);
-+    }
-+
-+    fn endpoint_set_in_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]) {
-+        if buf.len() != 8 {
-+            client_err!("Bad endpoint buffer size");
-+        }
-+
-+        self._endpoint_bank_set_buffer(EndpointIndex::new(endpoint), BankIndex::Bank0, buf);
-+    }
-+
-+    fn endpoint_set_out_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]) {
-+        if buf.len() != 8 {
-+            client_err!("Bad endpoint buffer size");
-+        }
-+
-+        // XXX: when implementing in_out endpoints, this should probably set a different slice than endpoint_set_in_buffer.
-         self._endpoint_bank_set_buffer(EndpointIndex::new(endpoint), BankIndex::Bank0, buf);
-     }
- 
-@@ -1547,10 +1564,6 @@ impl hil::usb::UsbController<'a> for Usbc<'a> {
-         requests.resume_out = true;
-         self.requests[endpoint].set(requests);
-     }
--
--    fn endpoint_cancel_in(&self, _endpoint: usize) {
--        unimplemented!()
--    }
- }
- 
- /// Static state to manage the USBC
-diff --git a/kernel/src/hil/usb.rs b/kernel/src/hil/usb.rs
-index 64610fa5..a114b30d 100644
---- a/kernel/src/hil/usb.rs
-+++ b/kernel/src/hil/usb.rs
-@@ -5,7 +5,9 @@ use crate::common::cells::VolatileCell;
- /// USB controller interface
- pub trait UsbController<'a> {
-     // Should be called before `enable_as_device()`
--    fn endpoint_set_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]);
-+    fn endpoint_set_ctrl_buffer(&self, buf: &'a [VolatileCell<u8>]);
-+    fn endpoint_set_in_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]);
-+    fn endpoint_set_out_buffer(&self, endpoint: usize, buf: &'a [VolatileCell<u8>]);
- 
-     // Must be called before `attach()`
-     fn enable_as_device(&self, speed: DeviceSpeed);
-@@ -27,8 +29,6 @@ pub trait UsbController<'a> {
-     fn endpoint_resume_in(&self, endpoint: usize);
- 
-     fn endpoint_resume_out(&self, endpoint: usize);
--
--    fn endpoint_cancel_in(&self, endpoint: usize);
- }
- 
- #[derive(Clone, Copy, Debug)]
diff --git a/third_party/tock b/third_party/tock
index fbc863f..7e47e6f 160000
--- a/third_party/tock
+++ b/third_party/tock
@@ -1 +1 @@
-Subproject commit fbc863faf0c9615537ee52dcdccdfcb9204d2467
+Subproject commit 7e47e6f1a9b279b6458edeb0fa24af381f5a1572
-- 
GitLab