From eac85f7e1ff354609695642408dfe31a617052d1 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Mon, 8 Apr 2024 12:42:16 +0200 Subject: [PATCH 1/2] Fix for incorrect poll rate on isochronous endpoints --- src/bus.rs | 26 ++++++++++++++++++ src/endpoint.rs | 73 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/bus.rs b/src/bus.rs index 35e43a9..450e02d 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -719,6 +719,22 @@ impl usb_device::bus::UsbBus for UsbBus { } } + if status == 0x02 { + if let Some(ep) = &self.allocator.endpoints_out[epnum as usize] { + if let EndpointType::Isochronous { + synchronization: _, + usage: _, + } = ep.ep_type() + { + let ep = regs.endpoint_out(epnum as usize); + let odd = read_reg!(endpoint_out, ep, DOEPCTL, EONUM_DPID); + modify_reg!(endpoint_out, ep, DOEPCTL, + SD0PID_SEVNFRM: odd as u32, + SODDFRM: !odd as u32); + } + } + } + if status == 0x02 || status == 0x06 { if let Some(ep) = &self.allocator.endpoints_out[epnum as usize] { let mut buffer = ep.buffer.borrow_ref_mut(cs); @@ -751,6 +767,16 @@ impl usb_device::bus::UsbBus for UsbBus { if let Some(ep) = ep { let ep_regs = regs.endpoint_in(ep.address().index()); if read_reg!(endpoint_in, ep_regs, DIEPINT, XFRC) != 0 { + if let EndpointType::Isochronous { + synchronization: _, + usage: _, + } = ep.ep_type() + { + let odd = read_reg!(endpoint_in, ep_regs, DIEPCTL, EONUM_DPID); + modify_reg!(endpoint_in, ep_regs, DIEPCTL, + SD0PID_SEVNFRM: odd as u32, + SODDFRM_SD1PID: !odd as u32); + } write_reg!(endpoint_in, ep_regs, DIEPINT, XFRC: 1); ep_in_complete |= 1 << ep.address().index(); } diff --git a/src/endpoint.rs b/src/endpoint.rs index c6e3be1..6a8e789 100644 --- a/src/endpoint.rs +++ b/src/endpoint.rs @@ -6,7 +6,7 @@ use crate::UsbPeripheral; use core::cell::RefCell; use core::ops::{Deref, DerefMut}; use critical_section::{CriticalSection, Mutex}; -use usb_device::endpoint::EndpointAddress; +use usb_device::endpoint::{EndpointAddress, EndpointType}; use usb_device::{Result, UsbDirection, UsbError}; pub fn set_stalled(usb: UsbRegisters, address: EndpointAddress, stalled: bool) { @@ -58,6 +58,10 @@ impl Endpoint { fn index(&self) -> u8 { self.descriptor.address.index() as u8 } + + pub fn ep_type(&self) -> EndpointType { + self.descriptor.ep_type + } } pub struct EndpointIn { @@ -86,14 +90,30 @@ impl EndpointIn { write_reg!(endpoint_in, regs, DIEPTSIZ, PKTCNT: 0, XFRSIZ: self.descriptor.max_packet_size as u32); } else { let regs = self.usb.endpoint_in(self.index() as usize); - write_reg!(endpoint_in, regs, DIEPCTL, - SNAK: 1, - USBAEP: 1, - EPTYP: self.descriptor.ep_type.to_bm_attributes() as u32, - SD0PID_SEVNFRM: 1, - TXFNUM: self.index() as u32, - MPSIZ: self.descriptor.max_packet_size as u32 - ); + if let EndpointType::Isochronous { + synchronization: _, + usage: _, + } = self.descriptor.ep_type + { + write_reg!(endpoint_in, regs, DIEPCTL, + SNAK: 1, + USBAEP: 1, + EPTYP: self.descriptor.ep_type.to_bm_attributes() as u32, + SD0PID_SEVNFRM: 1, + TXFNUM: self.index() as u32, + MPSIZ: self.descriptor.max_packet_size as u32, + EONUM_DPID: 0 + ); + } else { + write_reg!(endpoint_in, regs, DIEPCTL, + SNAK: 1, + USBAEP: 1, + EPTYP: self.descriptor.ep_type.to_bm_attributes() as u32, + SD0PID_SEVNFRM: 1, + TXFNUM: self.index() as u32, + MPSIZ: self.descriptor.max_packet_size as u32 + ); + } } } @@ -178,14 +198,33 @@ impl EndpointOut { modify_reg!(endpoint0_out, regs, DOEPCTL0, MPSIZ: mpsiz as u32, EPENA: 1, CNAK: 1); } else { let regs = self.usb.endpoint_out(self.index() as usize); - write_reg!(endpoint_out, regs, DOEPCTL, - SD0PID_SEVNFRM: 1, - CNAK: 1, - EPENA: 1, - USBAEP: 1, - EPTYP: self.descriptor.ep_type.to_bm_attributes() as u32, - MPSIZ: self.descriptor.max_packet_size as u32 - ); + if let EndpointType::Isochronous { + synchronization: _, + usage: _, + } = self.descriptor.ep_type + { + write_reg!(endpoint_out, regs, DOEPTSIZ, PKTCNT: 1, XFRSIZ: 0); + // let odd = read_reg!(otg_device, self.usb.device(), DSTS, FNSOF) & 0x01 == 1; + write_reg!(endpoint_out, regs, DOEPCTL, + //SODDFRM: 1, + SD0PID_SEVNFRM: 1, + CNAK: 1, + EPENA: 1, + USBAEP: 1, + EPTYP: self.descriptor.ep_type.to_bm_attributes() as u32, + MPSIZ: self.descriptor.max_packet_size as u32, + EONUM_DPID: 0 + ); + } else { + write_reg!(endpoint_out, regs, DOEPCTL, + SD0PID_SEVNFRM: 1, + CNAK: 1, + EPENA: 1, + USBAEP: 1, + EPTYP: self.descriptor.ep_type.to_bm_attributes() as u32, + MPSIZ: self.descriptor.max_packet_size as u32 + ); + } } } From 5c5a7fcc6595b70936eb0f9f2d2714dd67b82ef0 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Mon, 8 Apr 2024 17:41:15 +0200 Subject: [PATCH 2/2] Make isochronous endpoint fix work with HS feature --- src/bus.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bus.rs b/src/bus.rs index 450e02d..6e44521 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -773,9 +773,14 @@ impl usb_device::bus::UsbBus for UsbBus { } = ep.ep_type() { let odd = read_reg!(endpoint_in, ep_regs, DIEPCTL, EONUM_DPID); + #[cfg(feature = "fs")] modify_reg!(endpoint_in, ep_regs, DIEPCTL, SD0PID_SEVNFRM: odd as u32, SODDFRM_SD1PID: !odd as u32); + #[cfg(feature = "hs")] + modify_reg!(endpoint_in, ep_regs, DIEPCTL, + SD0PID_SEVNFRM: odd as u32, + SODDFRM: !odd as u32); } write_reg!(endpoint_in, ep_regs, DIEPINT, XFRC: 1); ep_in_complete |= 1 << ep.address().index();