aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usbh/src/pipe.rs59
1 files changed, 32 insertions, 27 deletions
diff --git a/usbh/src/pipe.rs b/usbh/src/pipe.rs
index e84b898..d880d7a 100644
--- a/usbh/src/pipe.rs
+++ b/usbh/src/pipe.rs
@@ -101,19 +101,14 @@ impl Pipe<'_, '_> {
info!("p{}: sending {:?}", self.num, buf);
- // Equiv to UHD_Pipe_Write(epAddr: 0, sizeof(setup_packet), &setup_packet)
self.desc
.bank0
.addr
.write(|w| unsafe { w.addr().bits(buf.ptr as u32) });
// configure packet size PCKSIZE.SIZE
self.desc.bank0.pcksize.write(|w| {
- // FIXME: write raw to pcksize, because byte_count offset
- // may be off? Doc table shows 6 bits, but text says 14,
- // and arduino shows 14.
- unsafe { w.bits(buf.len as u32) }
- //unsafe { w.byte_count().bits(buf.len as u8) };
- //unsafe { w.multi_packet_size().bits(0) }
+ unsafe { w.byte_count().bits(buf.len as u16) };
+ unsafe { w.multi_packet_size().bits(0) }
});
self.dispatch_retries(token, nak_limit, millis)
@@ -131,29 +126,39 @@ impl Pipe<'_, '_> {
assert!(buf.len < 16_384);
info!("p{}: Should IN for {}b.", self.num, buf.len);
- // TODO: should just pass pipe and pregs in, probably. TODO:
- // merge with stuff in `send_to_pipe` that also does this.
- self.desc
- .bank0
- .addr
- .write(|w| unsafe { w.addr().bits(buf.ptr as u32) });
self.desc.bank0.pcksize.write(|w| {
- // FIXME: see note in `send`.
- unsafe { w.bits(buf.len as u32) }
- //unsafe { w.byte_count().bits(buf.len as u8) };
- //unsafe { w.multi_packet_size().bits(0) }
+ unsafe { w.byte_count().bits(buf.len as u16) };
+ unsafe { w.multi_packet_size().bits(0) }
});
- // Possibly set PSTATUS.DTGL? Not sure how this works
- // yet. Arduino would set it here if dispatchPkt returned USB_ERROR_DATATOGGLE
- //pregs.statusset.write(|w| w.dtgl().set_bit());
- //pregs.statusclr.write(|w| unsafe {
- // No function for this. FIXME: need to patch the SVD for
- // PSTATUSCLR.DTGL at bit0
- // w.bits(1)
- //});
-
- self.dispatch_retries(USBToken::In, nak_limit, millis)
+ let mut bytes_received = 0;
+ while bytes_received < buf.len {
+ // Update buffer pointer.
+ //
+ // FIXME: This only works when the packet size is a word
+ // multiple, since `addr` requires word-aligned pointers.
+ self.desc
+ .bank0
+ .addr
+ .write(|w| unsafe { w.addr().bits(buf.ptr as u32 + bytes_received as u32) });
+ self.regs.statusclr.write(|w| w.bk0rdy().set_bit());
+
+ self.dispatch_retries(USBToken::In, nak_limit, millis)?;
+ bytes_received += self.desc.bank0.pcksize.read().byte_count().bits() as usize;
+ assert!(bytes_received <= buf.len);
+ info!("!! read {} of {}", bytes_received, buf.len);
+ }
+ self.regs.statusset.write(|w| w.pfreeze().set_bit());
+
+ if self.regs.status.read().dtgl().bit_is_set() {
+ self.regs.statusset.write(|w| w.dtgl().set_bit());
+ } else {
+ self.regs.statusclr.write(|w| unsafe {
+ // No function for this. FIXME: need to patch the SVD for PSTATUSCLR.DTGL at bit0
+ w.bits(1)
+ });
+ }
+ Ok(())
}
pub(crate) fn dispatch_retries(