Sync patches with upstream Tock.
This commit is contained in:
@@ -286,10 +286,10 @@ index 5abd2d84..5a726fdb 100644
|
|||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
diff --git a/kernel/src/callback.rs b/kernel/src/callback.rs
|
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
|
--- a/kernel/src/callback.rs
|
||||||
+++ b/kernel/src/callback.rs
|
+++ b/kernel/src/callback.rs
|
||||||
@@ -52,6 +52,31 @@ impl AppId {
|
@@ -130,6 +130,31 @@ impl AppId {
|
||||||
(start, end)
|
(start, end)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,11 +124,11 @@ index 105f7120..535e5cd8 100644
|
|||||||
ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
|
ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
|
||||||
nvmc: nvmc,
|
nvmc: nvmc,
|
||||||
diff --git a/capsules/src/driver.rs b/capsules/src/driver.rs
|
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
|
--- a/capsules/src/driver.rs
|
||||||
+++ b/capsules/src/driver.rs
|
+++ b/capsules/src/driver.rs
|
||||||
@@ -24,6 +24,7 @@ pub enum NUM {
|
@@ -25,6 +25,7 @@ pub enum NUM {
|
||||||
Spi = 0x20001,
|
I2cMaster = 0x20003,
|
||||||
UsbUser = 0x20005,
|
UsbUser = 0x20005,
|
||||||
I2cMasterSlave = 0x20006,
|
I2cMasterSlave = 0x20006,
|
||||||
+ UsbCtap = 0x20009,
|
+ 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
|
diff --git a/capsules/src/usb/usbc_ctap_hid.rs b/capsules/src/usb/usbc_ctap_hid.rs
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 00000000..fdf7263a
|
index 00000000..4b1916cf
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/capsules/src/usb/usbc_ctap_hid.rs
|
+++ 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
|
+//! A USB HID client of the USB hardware interface
|
||||||
+
|
+
|
||||||
+use super::descriptors::Buffer64;
|
+use super::descriptors::Buffer64;
|
||||||
@@ -603,8 +603,9 @@ index 00000000..fdf7263a
|
|||||||
+pub struct ClientCtapHID<'a, 'b, C: 'a> {
|
+pub struct ClientCtapHID<'a, 'b, C: 'a> {
|
||||||
+ client_ctrl: ClientCtrl<'a, 'static, C>,
|
+ client_ctrl: ClientCtrl<'a, 'static, C>,
|
||||||
+
|
+
|
||||||
+ // A 64-byte buffer for the endpoint
|
+ // 64-byte buffers for the endpoint
|
||||||
+ buffer: Buffer64,
|
+ in_buffer: Buffer64,
|
||||||
|
+ out_buffer: Buffer64,
|
||||||
+
|
+
|
||||||
+ // Interaction with the client
|
+ // Interaction with the client
|
||||||
+ client: OptionalCell<&'b dyn CtapUsbClient>,
|
+ client: OptionalCell<&'b dyn CtapUsbClient>,
|
||||||
@@ -648,7 +649,8 @@ index 00000000..fdf7263a
|
|||||||
+ LANGUAGES,
|
+ LANGUAGES,
|
||||||
+ STRINGS,
|
+ STRINGS,
|
||||||
+ ),
|
+ ),
|
||||||
+ buffer: Default::default(),
|
+ in_buffer: Default::default(),
|
||||||
|
+ out_buffer: Default::default(),
|
||||||
+ client: OptionalCell::empty(),
|
+ client: OptionalCell::empty(),
|
||||||
+ tx_packet: OptionalCell::empty(),
|
+ tx_packet: OptionalCell::empty(),
|
||||||
+ pending_in: Cell::new(false),
|
+ pending_in: Cell::new(false),
|
||||||
@@ -702,7 +704,7 @@ index 00000000..fdf7263a
|
|||||||
+ fn send_packet_to_client(&'a self) -> bool {
|
+ fn send_packet_to_client(&'a self) -> bool {
|
||||||
+ // Copy the packet into a buffer to send to the client.
|
+ // Copy the packet into a buffer to send to the client.
|
||||||
+ let mut buf: [u8; 64] = [0; 64];
|
+ 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();
|
+ buf[i] = x.get();
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
@@ -735,11 +737,7 @@ index 00000000..fdf7263a
|
|||||||
+
|
+
|
||||||
+ fn cancel_in_transaction(&'a self) -> bool {
|
+ fn cancel_in_transaction(&'a self) -> bool {
|
||||||
+ self.tx_packet.take();
|
+ self.tx_packet.take();
|
||||||
+ let result = self.pending_in.take();
|
+ self.pending_in.take()
|
||||||
+ if result {
|
|
||||||
+ self.controller().endpoint_cancel_in(1);
|
|
||||||
+ }
|
|
||||||
+ result
|
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ fn cancel_out_transaction(&'a self) -> bool {
|
+ fn cancel_out_transaction(&'a self) -> bool {
|
||||||
@@ -758,7 +756,10 @@ index 00000000..fdf7263a
|
|||||||
+ self.client_ctrl.enable();
|
+ self.client_ctrl.enable();
|
||||||
+
|
+
|
||||||
+ // Set up the interrupt in-out endpoint
|
+ // 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()
|
+ self.controller()
|
||||||
+ .endpoint_in_out_enable(TransferType::Interrupt, 1);
|
+ .endpoint_in_out_enable(TransferType::Interrupt, 1);
|
||||||
+ }
|
+ }
|
||||||
@@ -808,7 +809,7 @@ index 00000000..fdf7263a
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if let Some(packet) = self.tx_packet.take() {
|
+ if let Some(packet) = self.tx_packet.take() {
|
||||||
+ let buf = &self.buffer.buf;
|
+ let buf = &self.in_buffer.buf;
|
||||||
+ for i in 0..64 {
|
+ for i in 0..64 {
|
||||||
+ buf[i].set(packet[i]);
|
+ buf[i].set(packet[i]);
|
||||||
+ }
|
+ }
|
||||||
@@ -861,149 +862,13 @@ index 00000000..fdf7263a
|
|||||||
+ panic!("Unexpected tx_packet while a packet was being transmitted.");
|
+ panic!("Unexpected tx_packet while a packet was being transmitted.");
|
||||||
+ }
|
+ }
|
||||||
+ self.pending_in.set(false);
|
+ 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
|
+ // Notify the client
|
||||||
+ self.client.map(|client| client.packet_transmitted());
|
+ 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)]
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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)]
|
|
||||||
2
third_party/tock
vendored
2
third_party/tock
vendored
Submodule third_party/tock updated: fbc863faf0...7e47e6f1a9
Reference in New Issue
Block a user