aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-07-30 18:26:10 -0400
committerBrian Cully <bjc@kublai.com>2019-07-30 18:26:10 -0400
commit7f3601e081f71776d3b5f9fc58d5e1adda7772a3 (patch)
tree2be13a2d22d590719d8828b83afbe6fa31eceba0
parentfb45c6c269bb1440fdf8750bed875dfe973ca8bb (diff)
downloadsamd21-demo-7f3601e081f71776d3b5f9fc58d5e1adda7772a3.tar.gz
samd21-demo-7f3601e081f71776d3b5f9fc58d5e1adda7772a3.zip
WIP: Holy smokes I read my first keyboard report.
Too bad it's still trfail town after the first, but progress!
-rw-r--r--usbh/src/device.rs8
-rw-r--r--usbh/src/pipe.rs55
2 files changed, 52 insertions, 11 deletions
diff --git a/usbh/src/device.rs b/usbh/src/device.rs
index aaf82d1..6efc395 100644
--- a/usbh/src/device.rs
+++ b/usbh/src/device.rs
@@ -225,7 +225,7 @@ impl Device {
debug!(" -- idle set");
debug!("+++ setting report");
- let mut rep_res: u8 = 0;
+ let mut report: u8 = 0;
pipe.control_transfer(
RequestType::from((
RequestDirection::HostToDevice,
@@ -235,10 +235,10 @@ impl Device {
RequestCode::SetConfiguration,
WValue::from((0, 2)),
0,
- Some(&mut rep_res),
+ Some(&mut report),
self.millis,
)?;
- debug!(" -- report set: {}", rep_res);
+ debug!(" -- report set");
self.state = FSM::GetReport(3)
}
@@ -276,7 +276,7 @@ impl Device {
}
fn read_report(&mut self, pipe: &mut Pipe, id: u8) {
- let mut buf: core::mem::MaybeUninit<[u8; 64]> = core::mem::MaybeUninit::uninit();
+ let mut buf: core::mem::MaybeUninit<[u8; 8]> = core::mem::MaybeUninit::uninit();
match pipe.in_transfer(&mut buf, 15, self.millis) {
Ok(bytes_received) => {
let tmp = unsafe { &(buf.assume_init())[..bytes_received] };
diff --git a/usbh/src/pipe.rs b/usbh/src/pipe.rs
index 9b0eedd..d7b7981 100644
--- a/usbh/src/pipe.rs
+++ b/usbh/src/pipe.rs
@@ -19,7 +19,7 @@ use atsamd_hal::target_device::usb::{
host::{BINTERVAL, PCFG, PINTFLAG, PSTATUS, PSTATUSCLR, PSTATUSSET},
};
use core::convert::TryInto;
-use log::{debug, trace};
+use log::{trace, warn};
// Maximum time to wait for a control request with data to finish. cf
// ยง9.2.6.1 of USB 2.0.
@@ -149,7 +149,7 @@ impl Pipe<'_, '_> {
}
RequestDirection::HostToDevice => {
- debug!("Should OUT for {}b", len);
+ self.out_transfer(b, NAK_LIMIT, millis)?;
}
}
}
@@ -197,6 +197,36 @@ impl Pipe<'_, '_> {
self.dispatch_retries(token, nak_limit, millis)
}
+ pub(crate) fn out_transfer<T>(
+ &mut self,
+ buf: &mut T,
+ nak_limit: usize,
+ millis: &dyn Fn() -> usize,
+ ) -> Result<usize, PipeErr> {
+ let db: DataBuf = buf.into();
+
+ trace!("p{}: Should OUT for {}b.", self.num, db.len);
+ self.desc.bank0.pcksize.write(|w| {
+ unsafe { w.byte_count().bits(db.len as u16) };
+ unsafe { w.multi_packet_size().bits(0) }
+ });
+
+ let mut bytes_sent = 0;
+ while bytes_sent < db.len {
+ self.desc
+ .bank0
+ .addr
+ .write(|w| unsafe { w.addr().bits(db.ptr as u32 + bytes_sent as u32) });
+ self.dispatch_retries(PToken::Out, nak_limit, millis)?;
+
+ let sent = self.desc.bank0.pcksize.read().byte_count().bits() as usize;
+ bytes_sent += sent;
+ trace!("!! wrote {} of {}", bytes_sent, db.len);
+ }
+
+ Ok(bytes_sent)
+ }
+
pub(crate) fn in_transfer<T>(
&mut self,
buf: &mut T,
@@ -297,9 +327,6 @@ impl Pipe<'_, '_> {
retries: usize,
millis: &dyn Fn() -> usize,
) -> Result<(), PipeErr> {
- trace!("initial regs");
- self.log_regs();
-
self.dispatch_packet(token);
let until = millis() + USB_TIMEOUT;
@@ -328,8 +355,6 @@ impl Pipe<'_, '_> {
}
}
- trace!("dispatch err: {:?}", last_err);
- self.log_regs();
Err(last_err)
}
@@ -337,6 +362,10 @@ impl Pipe<'_, '_> {
self.regs
.cfg
.modify(|_, w| unsafe { w.ptoken().bits(token as u8) });
+
+ trace!("initial regs");
+ self.log_regs();
+
match token {
PToken::Setup => {
self.regs.intflag.write(|w| w.txstp().set_bit());
@@ -356,27 +385,39 @@ impl Pipe<'_, '_> {
if self.is_transfer_complete(token)? {
Ok(true)
} else if self.regs.intflag.read().stall().bit_is_set() {
+ warn!("stall");
+ self.log_regs();
self.regs.intflag.write(|w| w.stall().set_bit());
Err(PipeErr::Stall)
} else if self.regs.intflag.read().trfail().bit_is_set() {
+ warn!("trfail");
+ self.log_regs();
self.regs.intflag.write(|w| w.trfail().set_bit());
Err(PipeErr::TransferFail)
} else if self.regs.intflag.read().perr().bit_is_set() {
+ warn!("perr");
+ self.log_regs();
self.regs.intflag.write(|w| w.perr().set_bit());
Err(PipeErr::PipeErr)
} else if self.desc.bank0.status_bk.read().errorflow().bit_is_set() {
+ warn!("errorflow");
+ self.log_regs();
self.desc
.bank0
.status_bk
.write(|w| w.errorflow().clear_bit());
Err(PipeErr::Flow)
} else if self.desc.bank0.status_pipe.read().touter().bit_is_set() {
+ warn!("touter");
+ self.log_regs();
self.desc
.bank0
.status_pipe
.write(|w| w.touter().clear_bit());
Err(PipeErr::HWTimeout)
} else if self.desc.bank0.status_pipe.read().dtgler().bit_is_set() {
+ warn!("dtgler");
+ self.log_regs();
self.desc
.bank0
.status_pipe