diff options
-rw-r--r-- | usbh/src/pipe.rs | 59 |
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( |