Skip to content
Snippets Groups Projects
Commit 951268b5 authored by Guillaume Endignoux's avatar Guillaume Endignoux
Browse files

Add patch for bidirectional USB endpoints to fix panics in case of cancellation.

parent 47bd524c
No related branches found
No related tags found
No related merge requests found
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)]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment