Skip to content
Snippets Groups Projects
Unverified Commit fa427110 authored by gendx's avatar gendx Committed by GitHub
Browse files

Merge pull request #72 from gendx/fix-usb-cancellation

Add patch for bidirectional USB endpoints to fix panics in case of cancellation.
parents 47bd524c 951268b5
Branches
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.
Please register or to comment