stm32/usb_otg: prevent writes on disabled endpoint

This commit is contained in:
chemicstry 2023-01-18 02:31:28 +02:00
parent d2f2b451d0
commit f07e59b24a

View File

@ -1126,6 +1126,8 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> {
impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> { async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
trace!("write ep={} data={}", self.info.addr, buf);
if buf.len() > self.info.max_packet_size as usize { if buf.len() > self.info.max_packet_size as usize {
return Err(EndpointError::BufferOverflow); return Err(EndpointError::BufferOverflow);
} }
@ -1134,18 +1136,21 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
let index = self.info.addr.index(); let index = self.info.addr.index();
let state = T::state(); let state = T::state();
// Wait for previous transfer to complete // Wait for previous transfer to complete and check if endpoint is disabled
poll_fn(|cx| { poll_fn(|cx| {
state.ep_in_wakers[index].register(cx.waker()); state.ep_in_wakers[index].register(cx.waker());
// SAFETY: atomic read with no side effects // SAFETY: atomic read with no side effects
if unsafe { r.diepctl(index).read().epena() } { let diepctl = unsafe { r.diepctl(index).read() };
Poll::Pending if !diepctl.usbaep() {
Poll::Ready(Err(EndpointError::Disabled))
} else if !diepctl.epena() {
Poll::Ready(Ok(()))
} else { } else {
Poll::Ready(()) Poll::Pending
} }
}) })
.await; .await?;
if buf.len() > 0 { if buf.len() > 0 {
poll_fn(|cx| { poll_fn(|cx| {
@ -1201,7 +1206,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
unsafe { r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))) }; unsafe { r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))) };
} }
trace!("WRITE OK"); trace!("write done ep={}", self.info.addr);
Ok(()) Ok(())
} }
@ -1239,8 +1244,8 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> {
// Clear NAK to indicate we are ready to receive more data // Clear NAK to indicate we are ready to receive more data
T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| { T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| {
w.set_cnak(true); w.set_cnak(true);
}) });
}; }
trace!("SETUP received: {:?}", data); trace!("SETUP received: {:?}", data);
Poll::Ready(data) Poll::Ready(data)